Made it so you can whitelist what events you want to listen to (#17108)

This commit is contained in:
gaaclarke 2020-03-16 11:00:03 -07:00 committed by GitHub
parent 733933ad5c
commit fddb0c272e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 279 additions and 99 deletions

View File

@ -107,6 +107,9 @@ FILE: ../../../flutter/flow/view_holder.cc
FILE: ../../../flutter/flow/view_holder.h
FILE: ../../../flutter/flutter_frontend_server/bin/starter.dart
FILE: ../../../flutter/flutter_frontend_server/lib/server.dart
FILE: ../../../flutter/fml/ascii_trie.cc
FILE: ../../../flutter/fml/ascii_trie.h
FILE: ../../../flutter/fml/ascii_trie_unittests.cc
FILE: ../../../flutter/fml/backtrace.cc
FILE: ../../../flutter/fml/backtrace.h
FILE: ../../../flutter/fml/backtrace_stub.cc

View File

@ -91,6 +91,7 @@ struct Settings {
bool enable_checked_mode = false;
bool start_paused = false;
bool trace_skia = false;
std::string trace_whitelist;
bool trace_startup = false;
bool trace_systrace = false;
bool dump_skp_on_shader_compilation = false;

View File

@ -10,6 +10,8 @@ import("//flutter/testing/testing.gni")
source_set("fml") {
sources = [
"ascii_trie.cc",
"ascii_trie.h",
"backtrace.h",
"base32.cc",
"base32.h",
@ -236,6 +238,7 @@ executable("fml_unittests") {
testonly = true
sources = [
"ascii_trie_unittests.cc",
"backtrace_unittests.cc",
"base32_unittest.cc",
"command_line_unittest.cc",

48
fml/ascii_trie.cc Normal file
View File

@ -0,0 +1,48 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/fml/ascii_trie.h"
#include "flutter/fml/logging.h"
namespace fml {
typedef AsciiTrie::TrieNode TrieNode;
typedef AsciiTrie::TrieNodePtr TrieNodePtr;
namespace {
void Add(TrieNodePtr* trie, const char* entry) {
int ch = entry[0];
FML_DCHECK(ch < AsciiTrie::kMaxAsciiValue);
if (ch != 0) {
if (!*trie) {
*trie = std::make_unique<TrieNode>();
}
Add(&(*trie)->children[ch], entry + 1);
}
}
TrieNodePtr MakeTrie(const std::vector<std::string>& entries) {
TrieNodePtr result;
for (const std::string& entry : entries) {
Add(&result, entry.c_str());
}
return result;
}
} // namespace
void AsciiTrie::Fill(const std::vector<std::string>& entries) {
node_ = MakeTrie(entries);
}
bool AsciiTrie::Query(TrieNode* trie, const char* query) {
FML_DCHECK(trie);
const char* char_position = query;
TrieNode* trie_position = trie;
TrieNode* child;
int ch;
while ((ch = *char_position) && (child = trie_position->children[ch].get())) {
char_position++;
trie_position = child;
}
return !child && trie_position != trie;
}
} // namespace fml

39
fml/ascii_trie.h Normal file
View File

@ -0,0 +1,39 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FML_ASCIITRIE_H_
#define FLUTTER_FML_ASCIITRIE_H_
#include <string>
#include <vector>
namespace fml {
/// A trie for looking for ASCII prefixes.
class AsciiTrie {
public:
struct TrieNode;
typedef std::unique_ptr<TrieNode> TrieNodePtr;
/// The max Ascii value.
static const int kMaxAsciiValue = 128;
/// Clear and insert all the entries into the trie.
void Fill(const std::vector<std::string>& entries);
/// Returns true if \p argument is prefixed by the contents of the trie.
inline bool Query(const char* argument) {
return !node_ || Query(node_.get(), argument);
}
struct TrieNode {
TrieNodePtr children[kMaxAsciiValue];
};
private:
static bool Query(TrieNode* trie, const char* query);
TrieNodePtr node_;
};
} // namespace fml
#endif

View File

@ -0,0 +1,36 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/fml/ascii_trie.h"
#include "gtest/gtest.h"
using fml::AsciiTrie;
TEST(AsciiTableTest, Simple) {
AsciiTrie trie;
auto entries = std::vector<std::string>{"foo"};
trie.Fill(entries);
ASSERT_TRUE(trie.Query("foobar"));
ASSERT_FALSE(trie.Query("google"));
}
TEST(AsciiTableTest, ExactMatch) {
AsciiTrie trie;
auto entries = std::vector<std::string>{"foo"};
trie.Fill(entries);
ASSERT_TRUE(trie.Query("foo"));
}
TEST(AsciiTableTest, Empty) {
AsciiTrie trie;
ASSERT_TRUE(trie.Query("foo"));
}
TEST(AsciiTableTest, MultipleEntries) {
AsciiTrie trie;
auto entries = std::vector<std::string>{"foo", "bar"};
trie.Fill(entries);
ASSERT_TRUE(trie.Query("foozzz"));
ASSERT_TRUE(trie.Query("barzzz"));
}

View File

@ -8,6 +8,7 @@
#include <atomic>
#include <utility>
#include "flutter/fml/ascii_trie.h"
#include "flutter/fml/build_config.h"
#include "flutter/fml/logging.h"
@ -22,6 +23,27 @@ namespace tracing {
#if TIMELINE_ENABLED
namespace {
AsciiTrie gWhitelist;
inline void FlutterTimelineEvent(const char* label,
int64_t timestamp0,
int64_t timestamp1_or_async_id,
Dart_Timeline_Event_Type type,
intptr_t argument_count,
const char** argument_names,
const char** argument_values) {
if (gWhitelist.Query(label)) {
Dart_TimelineEvent(label, timestamp0, timestamp1_or_async_id, type,
argument_count, argument_names, argument_values);
}
}
} // namespace
void TraceSetWhitelist(const std::vector<std::string>& whitelist) {
gWhitelist.Fill(whitelist);
}
size_t TraceNonce() {
static std::atomic_size_t gLastItem;
return ++gLastItem;
@ -42,7 +64,7 @@ void TraceTimelineEvent(TraceArg category_group,
c_values[i] = values[i].c_str();
}
Dart_TimelineEvent(
FlutterTimelineEvent(
name, // label
Dart_TimelineGetMicros(), // timestamp0
identifier, // timestamp1_or_async_id
@ -54,13 +76,13 @@ void TraceTimelineEvent(TraceArg category_group,
}
void TraceEvent0(TraceArg category_group, TraceArg name) {
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_Begin, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_Begin, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}
@ -70,13 +92,13 @@ void TraceEvent1(TraceArg category_group,
TraceArg arg1_val) {
const char* arg_names[] = {arg1_name};
const char* arg_values[] = {arg1_val};
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_Begin, // event type
1, // argument_count
arg_names, // argument_names
arg_values // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_Begin, // event type
1, // argument_count
arg_names, // argument_names
arg_values // argument_values
);
}
@ -88,24 +110,24 @@ void TraceEvent2(TraceArg category_group,
TraceArg arg2_val) {
const char* arg_names[] = {arg1_name, arg2_name};
const char* arg_values[] = {arg1_val, arg2_val};
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_Begin, // event type
2, // argument_count
arg_names, // argument_names
arg_values // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_Begin, // event type
2, // argument_count
arg_names, // argument_names
arg_values // argument_values
);
}
void TraceEventEnd(TraceArg name) {
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_End, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_End, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}
@ -119,47 +141,47 @@ void TraceEventAsyncComplete(TraceArg category_group,
std::swap(begin, end);
}
Dart_TimelineEvent(name, // label
begin.ToEpochDelta().ToMicroseconds(), // timestamp0
identifier, // timestamp1_or_async_id
Dart_Timeline_Event_Async_Begin, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
begin.ToEpochDelta().ToMicroseconds(), // timestamp0
identifier, // timestamp1_or_async_id
Dart_Timeline_Event_Async_Begin, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
Dart_TimelineEvent(name, // label
end.ToEpochDelta().ToMicroseconds(), // timestamp0
identifier, // timestamp1_or_async_id
Dart_Timeline_Event_Async_End, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
end.ToEpochDelta().ToMicroseconds(), // timestamp0
identifier, // timestamp1_or_async_id
Dart_Timeline_Event_Async_End, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}
void TraceEventAsyncBegin0(TraceArg category_group,
TraceArg name,
TraceIDArg id) {
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Async_Begin, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Async_Begin, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}
void TraceEventAsyncEnd0(TraceArg category_group,
TraceArg name,
TraceIDArg id) {
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Async_End, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Async_End, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}
@ -170,13 +192,13 @@ void TraceEventAsyncBegin1(TraceArg category_group,
TraceArg arg1_val) {
const char* arg_names[] = {arg1_name};
const char* arg_values[] = {arg1_val};
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Async_Begin, // event type
1, // argument_count
arg_names, // argument_names
arg_values // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Async_Begin, // event type
1, // argument_count
arg_names, // argument_names
arg_values // argument_values
);
}
@ -187,66 +209,68 @@ void TraceEventAsyncEnd1(TraceArg category_group,
TraceArg arg1_val) {
const char* arg_names[] = {arg1_name};
const char* arg_values[] = {arg1_val};
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Async_End, // event type
1, // argument_count
arg_names, // argument_names
arg_values // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Async_End, // event type
1, // argument_count
arg_names, // argument_names
arg_values // argument_values
);
}
void TraceEventInstant0(TraceArg category_group, TraceArg name) {
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_Instant, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
0, // timestamp1_or_async_id
Dart_Timeline_Event_Instant, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}
void TraceEventFlowBegin0(TraceArg category_group,
TraceArg name,
TraceIDArg id) {
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Flow_Begin, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Flow_Begin, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}
void TraceEventFlowStep0(TraceArg category_group,
TraceArg name,
TraceIDArg id) {
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Flow_Step, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Flow_Step, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}
void TraceEventFlowEnd0(TraceArg category_group, TraceArg name, TraceIDArg id) {
Dart_TimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Flow_End, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
FlutterTimelineEvent(name, // label
Dart_TimelineGetMicros(), // timestamp0
id, // timestamp1_or_async_id
Dart_Timeline_Event_Flow_End, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}
#else // TIMELINE_ENABLED
void TraceSetWhitelist(const std::vector<std::string>& whitelist) {}
size_t TraceNonce() {
return 0;
}

View File

@ -112,6 +112,8 @@ namespace tracing {
using TraceArg = const char*;
using TraceIDArg = int64_t;
void TraceSetWhitelist(const std::vector<std::string>& whitelist);
void TraceTimelineEvent(TraceArg category_group,
TraceArg name,
TraceIDArg id,

View File

@ -180,6 +180,16 @@ static void RecordStartupTimestamp() {
}
}
static void Tokenize(const std::string& input,
std::vector<std::string>* results,
char delimiter) {
std::istringstream ss(input);
std::string token;
while (std::getline(ss, token, delimiter)) {
results->push_back(token);
}
}
// Though there can be multiple shells, some settings apply to all components in
// the process. These have to be setup before the shell or any of its
// sub-components can be initialized. In a perfect world, this would be empty.
@ -205,6 +215,12 @@ static void PerformInitializationTasks(const Settings& settings) {
InitSkiaEventTracer(settings.trace_skia);
}
if (!settings.trace_whitelist.empty()) {
std::vector<std::string> prefixes;
Tokenize(settings.trace_whitelist, &prefixes, ',');
fml::tracing::TraceSetWhitelist(prefixes);
}
if (!settings.skia_deterministic_rendering_on_cpu) {
SkGraphics::Init();
} else {

View File

@ -272,6 +272,9 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) {
settings.trace_skia =
command_line.HasOption(FlagForSwitch(Switch::TraceSkia));
command_line.GetOptionValue(FlagForSwitch(Switch::TraceWhitelist),
&settings.trace_whitelist);
settings.trace_systrace =
command_line.HasOption(FlagForSwitch(Switch::TraceSystrace));

View File

@ -129,6 +129,11 @@ DEF_SWITCH(TraceSkia,
"Trace Skia calls. This is useful when debugging the GPU threed."
"By default, Skia tracing is not enabled to reduce the number of "
"traced events")
DEF_SWITCH(
TraceWhitelist,
"trace-whitelist",
"Filters out all trace events except those that are specified in this "
"comma separated list of whitelisted prefixes.")
DEF_SWITCH(DumpSkpOnShaderCompilation,
"dump-skp-on-shader-compilation",
"Automatically dump the skp that triggers new shader compilations. "