1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/test/trace_event_analyzer.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <math.h>
8*635a8641SAndroid Build Coastguard Worker
9*635a8641SAndroid Build Coastguard Worker #include <algorithm>
10*635a8641SAndroid Build Coastguard Worker #include <set>
11*635a8641SAndroid Build Coastguard Worker
12*635a8641SAndroid Build Coastguard Worker #include "base/json/json_reader.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/memory/ref_counted_memory.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/run_loop.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/strings/pattern.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/trace_event/trace_buffer.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/trace_event/trace_config.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/trace_event/trace_log.h"
20*635a8641SAndroid Build Coastguard Worker #include "base/values.h"
21*635a8641SAndroid Build Coastguard Worker
22*635a8641SAndroid Build Coastguard Worker namespace {
OnTraceDataCollected(base::OnceClosure quit_closure,base::trace_event::TraceResultBuffer * buffer,const scoped_refptr<base::RefCountedString> & json,bool has_more_events)23*635a8641SAndroid Build Coastguard Worker void OnTraceDataCollected(base::OnceClosure quit_closure,
24*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceResultBuffer* buffer,
25*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::RefCountedString>& json,
26*635a8641SAndroid Build Coastguard Worker bool has_more_events) {
27*635a8641SAndroid Build Coastguard Worker buffer->AddFragment(json->data());
28*635a8641SAndroid Build Coastguard Worker if (!has_more_events)
29*635a8641SAndroid Build Coastguard Worker std::move(quit_closure).Run();
30*635a8641SAndroid Build Coastguard Worker }
31*635a8641SAndroid Build Coastguard Worker } // namespace
32*635a8641SAndroid Build Coastguard Worker
33*635a8641SAndroid Build Coastguard Worker namespace trace_analyzer {
34*635a8641SAndroid Build Coastguard Worker
35*635a8641SAndroid Build Coastguard Worker // TraceEvent
36*635a8641SAndroid Build Coastguard Worker
TraceEvent()37*635a8641SAndroid Build Coastguard Worker TraceEvent::TraceEvent()
38*635a8641SAndroid Build Coastguard Worker : thread(0, 0),
39*635a8641SAndroid Build Coastguard Worker timestamp(0),
40*635a8641SAndroid Build Coastguard Worker duration(0),
41*635a8641SAndroid Build Coastguard Worker phase(TRACE_EVENT_PHASE_BEGIN),
42*635a8641SAndroid Build Coastguard Worker other_event(nullptr) {}
43*635a8641SAndroid Build Coastguard Worker
44*635a8641SAndroid Build Coastguard Worker TraceEvent::TraceEvent(TraceEvent&& other) = default;
45*635a8641SAndroid Build Coastguard Worker
46*635a8641SAndroid Build Coastguard Worker TraceEvent::~TraceEvent() = default;
47*635a8641SAndroid Build Coastguard Worker
48*635a8641SAndroid Build Coastguard Worker TraceEvent& TraceEvent::operator=(TraceEvent&& rhs) = default;
49*635a8641SAndroid Build Coastguard Worker
SetFromJSON(const base::Value * event_value)50*635a8641SAndroid Build Coastguard Worker bool TraceEvent::SetFromJSON(const base::Value* event_value) {
51*635a8641SAndroid Build Coastguard Worker if (event_value->type() != base::Value::Type::DICTIONARY) {
52*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Value must be Type::DICTIONARY";
53*635a8641SAndroid Build Coastguard Worker return false;
54*635a8641SAndroid Build Coastguard Worker }
55*635a8641SAndroid Build Coastguard Worker const base::DictionaryValue* dictionary =
56*635a8641SAndroid Build Coastguard Worker static_cast<const base::DictionaryValue*>(event_value);
57*635a8641SAndroid Build Coastguard Worker
58*635a8641SAndroid Build Coastguard Worker std::string phase_str;
59*635a8641SAndroid Build Coastguard Worker const base::DictionaryValue* args = nullptr;
60*635a8641SAndroid Build Coastguard Worker
61*635a8641SAndroid Build Coastguard Worker if (!dictionary->GetString("ph", &phase_str)) {
62*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "ph is missing from TraceEvent JSON";
63*635a8641SAndroid Build Coastguard Worker return false;
64*635a8641SAndroid Build Coastguard Worker }
65*635a8641SAndroid Build Coastguard Worker
66*635a8641SAndroid Build Coastguard Worker phase = *phase_str.data();
67*635a8641SAndroid Build Coastguard Worker
68*635a8641SAndroid Build Coastguard Worker bool may_have_duration = (phase == TRACE_EVENT_PHASE_COMPLETE);
69*635a8641SAndroid Build Coastguard Worker bool require_origin = (phase != TRACE_EVENT_PHASE_METADATA);
70*635a8641SAndroid Build Coastguard Worker bool require_id = (phase == TRACE_EVENT_PHASE_ASYNC_BEGIN ||
71*635a8641SAndroid Build Coastguard Worker phase == TRACE_EVENT_PHASE_ASYNC_STEP_INTO ||
72*635a8641SAndroid Build Coastguard Worker phase == TRACE_EVENT_PHASE_ASYNC_STEP_PAST ||
73*635a8641SAndroid Build Coastguard Worker phase == TRACE_EVENT_PHASE_MEMORY_DUMP ||
74*635a8641SAndroid Build Coastguard Worker phase == TRACE_EVENT_PHASE_ENTER_CONTEXT ||
75*635a8641SAndroid Build Coastguard Worker phase == TRACE_EVENT_PHASE_LEAVE_CONTEXT ||
76*635a8641SAndroid Build Coastguard Worker phase == TRACE_EVENT_PHASE_CREATE_OBJECT ||
77*635a8641SAndroid Build Coastguard Worker phase == TRACE_EVENT_PHASE_DELETE_OBJECT ||
78*635a8641SAndroid Build Coastguard Worker phase == TRACE_EVENT_PHASE_SNAPSHOT_OBJECT ||
79*635a8641SAndroid Build Coastguard Worker phase == TRACE_EVENT_PHASE_ASYNC_END);
80*635a8641SAndroid Build Coastguard Worker
81*635a8641SAndroid Build Coastguard Worker if (require_origin && !dictionary->GetInteger("pid", &thread.process_id)) {
82*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "pid is missing from TraceEvent JSON";
83*635a8641SAndroid Build Coastguard Worker return false;
84*635a8641SAndroid Build Coastguard Worker }
85*635a8641SAndroid Build Coastguard Worker if (require_origin && !dictionary->GetInteger("tid", &thread.thread_id)) {
86*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "tid is missing from TraceEvent JSON";
87*635a8641SAndroid Build Coastguard Worker return false;
88*635a8641SAndroid Build Coastguard Worker }
89*635a8641SAndroid Build Coastguard Worker if (require_origin && !dictionary->GetDouble("ts", ×tamp)) {
90*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "ts is missing from TraceEvent JSON";
91*635a8641SAndroid Build Coastguard Worker return false;
92*635a8641SAndroid Build Coastguard Worker }
93*635a8641SAndroid Build Coastguard Worker if (may_have_duration) {
94*635a8641SAndroid Build Coastguard Worker dictionary->GetDouble("dur", &duration);
95*635a8641SAndroid Build Coastguard Worker }
96*635a8641SAndroid Build Coastguard Worker if (!dictionary->GetString("cat", &category)) {
97*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "cat is missing from TraceEvent JSON";
98*635a8641SAndroid Build Coastguard Worker return false;
99*635a8641SAndroid Build Coastguard Worker }
100*635a8641SAndroid Build Coastguard Worker if (!dictionary->GetString("name", &name)) {
101*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "name is missing from TraceEvent JSON";
102*635a8641SAndroid Build Coastguard Worker return false;
103*635a8641SAndroid Build Coastguard Worker }
104*635a8641SAndroid Build Coastguard Worker if (!dictionary->GetDictionary("args", &args)) {
105*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "args is missing from TraceEvent JSON";
106*635a8641SAndroid Build Coastguard Worker return false;
107*635a8641SAndroid Build Coastguard Worker }
108*635a8641SAndroid Build Coastguard Worker if (require_id && !dictionary->GetString("id", &id)) {
109*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "id is missing from ASYNC_BEGIN/ASYNC_END TraceEvent JSON";
110*635a8641SAndroid Build Coastguard Worker return false;
111*635a8641SAndroid Build Coastguard Worker }
112*635a8641SAndroid Build Coastguard Worker
113*635a8641SAndroid Build Coastguard Worker dictionary->GetDouble("tdur", &thread_duration);
114*635a8641SAndroid Build Coastguard Worker dictionary->GetDouble("tts", &thread_timestamp);
115*635a8641SAndroid Build Coastguard Worker dictionary->GetString("scope", &scope);
116*635a8641SAndroid Build Coastguard Worker dictionary->GetString("bind_id", &bind_id);
117*635a8641SAndroid Build Coastguard Worker dictionary->GetBoolean("flow_out", &flow_out);
118*635a8641SAndroid Build Coastguard Worker dictionary->GetBoolean("flow_in", &flow_in);
119*635a8641SAndroid Build Coastguard Worker
120*635a8641SAndroid Build Coastguard Worker const base::DictionaryValue* id2;
121*635a8641SAndroid Build Coastguard Worker if (dictionary->GetDictionary("id2", &id2)) {
122*635a8641SAndroid Build Coastguard Worker id2->GetString("global", &global_id2);
123*635a8641SAndroid Build Coastguard Worker id2->GetString("local", &local_id2);
124*635a8641SAndroid Build Coastguard Worker }
125*635a8641SAndroid Build Coastguard Worker
126*635a8641SAndroid Build Coastguard Worker // For each argument, copy the type and create a trace_analyzer::TraceValue.
127*635a8641SAndroid Build Coastguard Worker for (base::DictionaryValue::Iterator it(*args); !it.IsAtEnd();
128*635a8641SAndroid Build Coastguard Worker it.Advance()) {
129*635a8641SAndroid Build Coastguard Worker std::string str;
130*635a8641SAndroid Build Coastguard Worker bool boolean = false;
131*635a8641SAndroid Build Coastguard Worker int int_num = 0;
132*635a8641SAndroid Build Coastguard Worker double double_num = 0.0;
133*635a8641SAndroid Build Coastguard Worker if (it.value().GetAsString(&str)) {
134*635a8641SAndroid Build Coastguard Worker arg_strings[it.key()] = str;
135*635a8641SAndroid Build Coastguard Worker } else if (it.value().GetAsInteger(&int_num)) {
136*635a8641SAndroid Build Coastguard Worker arg_numbers[it.key()] = static_cast<double>(int_num);
137*635a8641SAndroid Build Coastguard Worker } else if (it.value().GetAsBoolean(&boolean)) {
138*635a8641SAndroid Build Coastguard Worker arg_numbers[it.key()] = static_cast<double>(boolean ? 1 : 0);
139*635a8641SAndroid Build Coastguard Worker } else if (it.value().GetAsDouble(&double_num)) {
140*635a8641SAndroid Build Coastguard Worker arg_numbers[it.key()] = double_num;
141*635a8641SAndroid Build Coastguard Worker }
142*635a8641SAndroid Build Coastguard Worker // Record all arguments as values.
143*635a8641SAndroid Build Coastguard Worker arg_values[it.key()] = it.value().CreateDeepCopy();
144*635a8641SAndroid Build Coastguard Worker }
145*635a8641SAndroid Build Coastguard Worker
146*635a8641SAndroid Build Coastguard Worker return true;
147*635a8641SAndroid Build Coastguard Worker }
148*635a8641SAndroid Build Coastguard Worker
GetAbsTimeToOtherEvent() const149*635a8641SAndroid Build Coastguard Worker double TraceEvent::GetAbsTimeToOtherEvent() const {
150*635a8641SAndroid Build Coastguard Worker return fabs(other_event->timestamp - timestamp);
151*635a8641SAndroid Build Coastguard Worker }
152*635a8641SAndroid Build Coastguard Worker
GetArgAsString(const std::string & name,std::string * arg) const153*635a8641SAndroid Build Coastguard Worker bool TraceEvent::GetArgAsString(const std::string& name,
154*635a8641SAndroid Build Coastguard Worker std::string* arg) const {
155*635a8641SAndroid Build Coastguard Worker const auto it = arg_strings.find(name);
156*635a8641SAndroid Build Coastguard Worker if (it != arg_strings.end()) {
157*635a8641SAndroid Build Coastguard Worker *arg = it->second;
158*635a8641SAndroid Build Coastguard Worker return true;
159*635a8641SAndroid Build Coastguard Worker }
160*635a8641SAndroid Build Coastguard Worker return false;
161*635a8641SAndroid Build Coastguard Worker }
162*635a8641SAndroid Build Coastguard Worker
GetArgAsNumber(const std::string & name,double * arg) const163*635a8641SAndroid Build Coastguard Worker bool TraceEvent::GetArgAsNumber(const std::string& name,
164*635a8641SAndroid Build Coastguard Worker double* arg) const {
165*635a8641SAndroid Build Coastguard Worker const auto it = arg_numbers.find(name);
166*635a8641SAndroid Build Coastguard Worker if (it != arg_numbers.end()) {
167*635a8641SAndroid Build Coastguard Worker *arg = it->second;
168*635a8641SAndroid Build Coastguard Worker return true;
169*635a8641SAndroid Build Coastguard Worker }
170*635a8641SAndroid Build Coastguard Worker return false;
171*635a8641SAndroid Build Coastguard Worker }
172*635a8641SAndroid Build Coastguard Worker
GetArgAsValue(const std::string & name,std::unique_ptr<base::Value> * arg) const173*635a8641SAndroid Build Coastguard Worker bool TraceEvent::GetArgAsValue(const std::string& name,
174*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::Value>* arg) const {
175*635a8641SAndroid Build Coastguard Worker const auto it = arg_values.find(name);
176*635a8641SAndroid Build Coastguard Worker if (it != arg_values.end()) {
177*635a8641SAndroid Build Coastguard Worker *arg = it->second->CreateDeepCopy();
178*635a8641SAndroid Build Coastguard Worker return true;
179*635a8641SAndroid Build Coastguard Worker }
180*635a8641SAndroid Build Coastguard Worker return false;
181*635a8641SAndroid Build Coastguard Worker }
182*635a8641SAndroid Build Coastguard Worker
HasStringArg(const std::string & name) const183*635a8641SAndroid Build Coastguard Worker bool TraceEvent::HasStringArg(const std::string& name) const {
184*635a8641SAndroid Build Coastguard Worker return (arg_strings.find(name) != arg_strings.end());
185*635a8641SAndroid Build Coastguard Worker }
186*635a8641SAndroid Build Coastguard Worker
HasNumberArg(const std::string & name) const187*635a8641SAndroid Build Coastguard Worker bool TraceEvent::HasNumberArg(const std::string& name) const {
188*635a8641SAndroid Build Coastguard Worker return (arg_numbers.find(name) != arg_numbers.end());
189*635a8641SAndroid Build Coastguard Worker }
190*635a8641SAndroid Build Coastguard Worker
HasArg(const std::string & name) const191*635a8641SAndroid Build Coastguard Worker bool TraceEvent::HasArg(const std::string& name) const {
192*635a8641SAndroid Build Coastguard Worker return (arg_values.find(name) != arg_values.end());
193*635a8641SAndroid Build Coastguard Worker }
194*635a8641SAndroid Build Coastguard Worker
GetKnownArgAsString(const std::string & name) const195*635a8641SAndroid Build Coastguard Worker std::string TraceEvent::GetKnownArgAsString(const std::string& name) const {
196*635a8641SAndroid Build Coastguard Worker std::string arg_string;
197*635a8641SAndroid Build Coastguard Worker bool result = GetArgAsString(name, &arg_string);
198*635a8641SAndroid Build Coastguard Worker DCHECK(result);
199*635a8641SAndroid Build Coastguard Worker return arg_string;
200*635a8641SAndroid Build Coastguard Worker }
201*635a8641SAndroid Build Coastguard Worker
GetKnownArgAsDouble(const std::string & name) const202*635a8641SAndroid Build Coastguard Worker double TraceEvent::GetKnownArgAsDouble(const std::string& name) const {
203*635a8641SAndroid Build Coastguard Worker double arg_double = 0;
204*635a8641SAndroid Build Coastguard Worker bool result = GetArgAsNumber(name, &arg_double);
205*635a8641SAndroid Build Coastguard Worker DCHECK(result);
206*635a8641SAndroid Build Coastguard Worker return arg_double;
207*635a8641SAndroid Build Coastguard Worker }
208*635a8641SAndroid Build Coastguard Worker
GetKnownArgAsInt(const std::string & name) const209*635a8641SAndroid Build Coastguard Worker int TraceEvent::GetKnownArgAsInt(const std::string& name) const {
210*635a8641SAndroid Build Coastguard Worker double arg_double = 0;
211*635a8641SAndroid Build Coastguard Worker bool result = GetArgAsNumber(name, &arg_double);
212*635a8641SAndroid Build Coastguard Worker DCHECK(result);
213*635a8641SAndroid Build Coastguard Worker return static_cast<int>(arg_double);
214*635a8641SAndroid Build Coastguard Worker }
215*635a8641SAndroid Build Coastguard Worker
GetKnownArgAsBool(const std::string & name) const216*635a8641SAndroid Build Coastguard Worker bool TraceEvent::GetKnownArgAsBool(const std::string& name) const {
217*635a8641SAndroid Build Coastguard Worker double arg_double = 0;
218*635a8641SAndroid Build Coastguard Worker bool result = GetArgAsNumber(name, &arg_double);
219*635a8641SAndroid Build Coastguard Worker DCHECK(result);
220*635a8641SAndroid Build Coastguard Worker return (arg_double != 0.0);
221*635a8641SAndroid Build Coastguard Worker }
222*635a8641SAndroid Build Coastguard Worker
GetKnownArgAsValue(const std::string & name) const223*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::Value> TraceEvent::GetKnownArgAsValue(
224*635a8641SAndroid Build Coastguard Worker const std::string& name) const {
225*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::Value> arg_value;
226*635a8641SAndroid Build Coastguard Worker bool result = GetArgAsValue(name, &arg_value);
227*635a8641SAndroid Build Coastguard Worker DCHECK(result);
228*635a8641SAndroid Build Coastguard Worker return arg_value;
229*635a8641SAndroid Build Coastguard Worker }
230*635a8641SAndroid Build Coastguard Worker
231*635a8641SAndroid Build Coastguard Worker // QueryNode
232*635a8641SAndroid Build Coastguard Worker
QueryNode(const Query & query)233*635a8641SAndroid Build Coastguard Worker QueryNode::QueryNode(const Query& query) : query_(query) {
234*635a8641SAndroid Build Coastguard Worker }
235*635a8641SAndroid Build Coastguard Worker
236*635a8641SAndroid Build Coastguard Worker QueryNode::~QueryNode() = default;
237*635a8641SAndroid Build Coastguard Worker
238*635a8641SAndroid Build Coastguard Worker // Query
239*635a8641SAndroid Build Coastguard Worker
Query(TraceEventMember member)240*635a8641SAndroid Build Coastguard Worker Query::Query(TraceEventMember member)
241*635a8641SAndroid Build Coastguard Worker : type_(QUERY_EVENT_MEMBER),
242*635a8641SAndroid Build Coastguard Worker operator_(OP_INVALID),
243*635a8641SAndroid Build Coastguard Worker member_(member),
244*635a8641SAndroid Build Coastguard Worker number_(0),
245*635a8641SAndroid Build Coastguard Worker is_pattern_(false) {
246*635a8641SAndroid Build Coastguard Worker }
247*635a8641SAndroid Build Coastguard Worker
Query(TraceEventMember member,const std::string & arg_name)248*635a8641SAndroid Build Coastguard Worker Query::Query(TraceEventMember member, const std::string& arg_name)
249*635a8641SAndroid Build Coastguard Worker : type_(QUERY_EVENT_MEMBER),
250*635a8641SAndroid Build Coastguard Worker operator_(OP_INVALID),
251*635a8641SAndroid Build Coastguard Worker member_(member),
252*635a8641SAndroid Build Coastguard Worker number_(0),
253*635a8641SAndroid Build Coastguard Worker string_(arg_name),
254*635a8641SAndroid Build Coastguard Worker is_pattern_(false) {
255*635a8641SAndroid Build Coastguard Worker }
256*635a8641SAndroid Build Coastguard Worker
257*635a8641SAndroid Build Coastguard Worker Query::Query(const Query& query) = default;
258*635a8641SAndroid Build Coastguard Worker
259*635a8641SAndroid Build Coastguard Worker Query::~Query() = default;
260*635a8641SAndroid Build Coastguard Worker
String(const std::string & str)261*635a8641SAndroid Build Coastguard Worker Query Query::String(const std::string& str) {
262*635a8641SAndroid Build Coastguard Worker return Query(str);
263*635a8641SAndroid Build Coastguard Worker }
264*635a8641SAndroid Build Coastguard Worker
Double(double num)265*635a8641SAndroid Build Coastguard Worker Query Query::Double(double num) {
266*635a8641SAndroid Build Coastguard Worker return Query(num);
267*635a8641SAndroid Build Coastguard Worker }
268*635a8641SAndroid Build Coastguard Worker
Int(int32_t num)269*635a8641SAndroid Build Coastguard Worker Query Query::Int(int32_t num) {
270*635a8641SAndroid Build Coastguard Worker return Query(static_cast<double>(num));
271*635a8641SAndroid Build Coastguard Worker }
272*635a8641SAndroid Build Coastguard Worker
Uint(uint32_t num)273*635a8641SAndroid Build Coastguard Worker Query Query::Uint(uint32_t num) {
274*635a8641SAndroid Build Coastguard Worker return Query(static_cast<double>(num));
275*635a8641SAndroid Build Coastguard Worker }
276*635a8641SAndroid Build Coastguard Worker
Bool(bool boolean)277*635a8641SAndroid Build Coastguard Worker Query Query::Bool(bool boolean) {
278*635a8641SAndroid Build Coastguard Worker return Query(boolean ? 1.0 : 0.0);
279*635a8641SAndroid Build Coastguard Worker }
280*635a8641SAndroid Build Coastguard Worker
Phase(char phase)281*635a8641SAndroid Build Coastguard Worker Query Query::Phase(char phase) {
282*635a8641SAndroid Build Coastguard Worker return Query(static_cast<double>(phase));
283*635a8641SAndroid Build Coastguard Worker }
284*635a8641SAndroid Build Coastguard Worker
Pattern(const std::string & pattern)285*635a8641SAndroid Build Coastguard Worker Query Query::Pattern(const std::string& pattern) {
286*635a8641SAndroid Build Coastguard Worker Query query(pattern);
287*635a8641SAndroid Build Coastguard Worker query.is_pattern_ = true;
288*635a8641SAndroid Build Coastguard Worker return query;
289*635a8641SAndroid Build Coastguard Worker }
290*635a8641SAndroid Build Coastguard Worker
Evaluate(const TraceEvent & event) const291*635a8641SAndroid Build Coastguard Worker bool Query::Evaluate(const TraceEvent& event) const {
292*635a8641SAndroid Build Coastguard Worker // First check for values that can convert to bool.
293*635a8641SAndroid Build Coastguard Worker
294*635a8641SAndroid Build Coastguard Worker // double is true if != 0:
295*635a8641SAndroid Build Coastguard Worker double bool_value = 0.0;
296*635a8641SAndroid Build Coastguard Worker bool is_bool = GetAsDouble(event, &bool_value);
297*635a8641SAndroid Build Coastguard Worker if (is_bool)
298*635a8641SAndroid Build Coastguard Worker return (bool_value != 0.0);
299*635a8641SAndroid Build Coastguard Worker
300*635a8641SAndroid Build Coastguard Worker // string is true if it is non-empty:
301*635a8641SAndroid Build Coastguard Worker std::string str_value;
302*635a8641SAndroid Build Coastguard Worker bool is_str = GetAsString(event, &str_value);
303*635a8641SAndroid Build Coastguard Worker if (is_str)
304*635a8641SAndroid Build Coastguard Worker return !str_value.empty();
305*635a8641SAndroid Build Coastguard Worker
306*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(QUERY_BOOLEAN_OPERATOR, type_)
307*635a8641SAndroid Build Coastguard Worker << "Invalid query: missing boolean expression";
308*635a8641SAndroid Build Coastguard Worker DCHECK(left_.get());
309*635a8641SAndroid Build Coastguard Worker DCHECK(right_.get() || is_unary_operator());
310*635a8641SAndroid Build Coastguard Worker
311*635a8641SAndroid Build Coastguard Worker if (is_comparison_operator()) {
312*635a8641SAndroid Build Coastguard Worker DCHECK(left().is_value() && right().is_value())
313*635a8641SAndroid Build Coastguard Worker << "Invalid query: comparison operator used between event member and "
314*635a8641SAndroid Build Coastguard Worker "value.";
315*635a8641SAndroid Build Coastguard Worker bool compare_result = false;
316*635a8641SAndroid Build Coastguard Worker if (CompareAsDouble(event, &compare_result))
317*635a8641SAndroid Build Coastguard Worker return compare_result;
318*635a8641SAndroid Build Coastguard Worker if (CompareAsString(event, &compare_result))
319*635a8641SAndroid Build Coastguard Worker return compare_result;
320*635a8641SAndroid Build Coastguard Worker return false;
321*635a8641SAndroid Build Coastguard Worker }
322*635a8641SAndroid Build Coastguard Worker // It's a logical operator.
323*635a8641SAndroid Build Coastguard Worker switch (operator_) {
324*635a8641SAndroid Build Coastguard Worker case OP_AND:
325*635a8641SAndroid Build Coastguard Worker return left().Evaluate(event) && right().Evaluate(event);
326*635a8641SAndroid Build Coastguard Worker case OP_OR:
327*635a8641SAndroid Build Coastguard Worker return left().Evaluate(event) || right().Evaluate(event);
328*635a8641SAndroid Build Coastguard Worker case OP_NOT:
329*635a8641SAndroid Build Coastguard Worker return !left().Evaluate(event);
330*635a8641SAndroid Build Coastguard Worker default:
331*635a8641SAndroid Build Coastguard Worker NOTREACHED();
332*635a8641SAndroid Build Coastguard Worker return false;
333*635a8641SAndroid Build Coastguard Worker }
334*635a8641SAndroid Build Coastguard Worker }
335*635a8641SAndroid Build Coastguard Worker
CompareAsDouble(const TraceEvent & event,bool * result) const336*635a8641SAndroid Build Coastguard Worker bool Query::CompareAsDouble(const TraceEvent& event, bool* result) const {
337*635a8641SAndroid Build Coastguard Worker double lhs, rhs;
338*635a8641SAndroid Build Coastguard Worker if (!left().GetAsDouble(event, &lhs) || !right().GetAsDouble(event, &rhs))
339*635a8641SAndroid Build Coastguard Worker return false;
340*635a8641SAndroid Build Coastguard Worker switch (operator_) {
341*635a8641SAndroid Build Coastguard Worker case OP_EQ:
342*635a8641SAndroid Build Coastguard Worker *result = (lhs == rhs);
343*635a8641SAndroid Build Coastguard Worker return true;
344*635a8641SAndroid Build Coastguard Worker case OP_NE:
345*635a8641SAndroid Build Coastguard Worker *result = (lhs != rhs);
346*635a8641SAndroid Build Coastguard Worker return true;
347*635a8641SAndroid Build Coastguard Worker case OP_LT:
348*635a8641SAndroid Build Coastguard Worker *result = (lhs < rhs);
349*635a8641SAndroid Build Coastguard Worker return true;
350*635a8641SAndroid Build Coastguard Worker case OP_LE:
351*635a8641SAndroid Build Coastguard Worker *result = (lhs <= rhs);
352*635a8641SAndroid Build Coastguard Worker return true;
353*635a8641SAndroid Build Coastguard Worker case OP_GT:
354*635a8641SAndroid Build Coastguard Worker *result = (lhs > rhs);
355*635a8641SAndroid Build Coastguard Worker return true;
356*635a8641SAndroid Build Coastguard Worker case OP_GE:
357*635a8641SAndroid Build Coastguard Worker *result = (lhs >= rhs);
358*635a8641SAndroid Build Coastguard Worker return true;
359*635a8641SAndroid Build Coastguard Worker default:
360*635a8641SAndroid Build Coastguard Worker NOTREACHED();
361*635a8641SAndroid Build Coastguard Worker return false;
362*635a8641SAndroid Build Coastguard Worker }
363*635a8641SAndroid Build Coastguard Worker }
364*635a8641SAndroid Build Coastguard Worker
CompareAsString(const TraceEvent & event,bool * result) const365*635a8641SAndroid Build Coastguard Worker bool Query::CompareAsString(const TraceEvent& event, bool* result) const {
366*635a8641SAndroid Build Coastguard Worker std::string lhs, rhs;
367*635a8641SAndroid Build Coastguard Worker if (!left().GetAsString(event, &lhs) || !right().GetAsString(event, &rhs))
368*635a8641SAndroid Build Coastguard Worker return false;
369*635a8641SAndroid Build Coastguard Worker switch (operator_) {
370*635a8641SAndroid Build Coastguard Worker case OP_EQ:
371*635a8641SAndroid Build Coastguard Worker if (right().is_pattern_)
372*635a8641SAndroid Build Coastguard Worker *result = base::MatchPattern(lhs, rhs);
373*635a8641SAndroid Build Coastguard Worker else if (left().is_pattern_)
374*635a8641SAndroid Build Coastguard Worker *result = base::MatchPattern(rhs, lhs);
375*635a8641SAndroid Build Coastguard Worker else
376*635a8641SAndroid Build Coastguard Worker *result = (lhs == rhs);
377*635a8641SAndroid Build Coastguard Worker return true;
378*635a8641SAndroid Build Coastguard Worker case OP_NE:
379*635a8641SAndroid Build Coastguard Worker if (right().is_pattern_)
380*635a8641SAndroid Build Coastguard Worker *result = !base::MatchPattern(lhs, rhs);
381*635a8641SAndroid Build Coastguard Worker else if (left().is_pattern_)
382*635a8641SAndroid Build Coastguard Worker *result = !base::MatchPattern(rhs, lhs);
383*635a8641SAndroid Build Coastguard Worker else
384*635a8641SAndroid Build Coastguard Worker *result = (lhs != rhs);
385*635a8641SAndroid Build Coastguard Worker return true;
386*635a8641SAndroid Build Coastguard Worker case OP_LT:
387*635a8641SAndroid Build Coastguard Worker *result = (lhs < rhs);
388*635a8641SAndroid Build Coastguard Worker return true;
389*635a8641SAndroid Build Coastguard Worker case OP_LE:
390*635a8641SAndroid Build Coastguard Worker *result = (lhs <= rhs);
391*635a8641SAndroid Build Coastguard Worker return true;
392*635a8641SAndroid Build Coastguard Worker case OP_GT:
393*635a8641SAndroid Build Coastguard Worker *result = (lhs > rhs);
394*635a8641SAndroid Build Coastguard Worker return true;
395*635a8641SAndroid Build Coastguard Worker case OP_GE:
396*635a8641SAndroid Build Coastguard Worker *result = (lhs >= rhs);
397*635a8641SAndroid Build Coastguard Worker return true;
398*635a8641SAndroid Build Coastguard Worker default:
399*635a8641SAndroid Build Coastguard Worker NOTREACHED();
400*635a8641SAndroid Build Coastguard Worker return false;
401*635a8641SAndroid Build Coastguard Worker }
402*635a8641SAndroid Build Coastguard Worker }
403*635a8641SAndroid Build Coastguard Worker
EvaluateArithmeticOperator(const TraceEvent & event,double * num) const404*635a8641SAndroid Build Coastguard Worker bool Query::EvaluateArithmeticOperator(const TraceEvent& event,
405*635a8641SAndroid Build Coastguard Worker double* num) const {
406*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(QUERY_ARITHMETIC_OPERATOR, type_);
407*635a8641SAndroid Build Coastguard Worker DCHECK(left_.get());
408*635a8641SAndroid Build Coastguard Worker DCHECK(right_.get() || is_unary_operator());
409*635a8641SAndroid Build Coastguard Worker
410*635a8641SAndroid Build Coastguard Worker double lhs = 0, rhs = 0;
411*635a8641SAndroid Build Coastguard Worker if (!left().GetAsDouble(event, &lhs))
412*635a8641SAndroid Build Coastguard Worker return false;
413*635a8641SAndroid Build Coastguard Worker if (!is_unary_operator() && !right().GetAsDouble(event, &rhs))
414*635a8641SAndroid Build Coastguard Worker return false;
415*635a8641SAndroid Build Coastguard Worker
416*635a8641SAndroid Build Coastguard Worker switch (operator_) {
417*635a8641SAndroid Build Coastguard Worker case OP_ADD:
418*635a8641SAndroid Build Coastguard Worker *num = lhs + rhs;
419*635a8641SAndroid Build Coastguard Worker return true;
420*635a8641SAndroid Build Coastguard Worker case OP_SUB:
421*635a8641SAndroid Build Coastguard Worker *num = lhs - rhs;
422*635a8641SAndroid Build Coastguard Worker return true;
423*635a8641SAndroid Build Coastguard Worker case OP_MUL:
424*635a8641SAndroid Build Coastguard Worker *num = lhs * rhs;
425*635a8641SAndroid Build Coastguard Worker return true;
426*635a8641SAndroid Build Coastguard Worker case OP_DIV:
427*635a8641SAndroid Build Coastguard Worker *num = lhs / rhs;
428*635a8641SAndroid Build Coastguard Worker return true;
429*635a8641SAndroid Build Coastguard Worker case OP_MOD:
430*635a8641SAndroid Build Coastguard Worker *num = static_cast<double>(static_cast<int64_t>(lhs) %
431*635a8641SAndroid Build Coastguard Worker static_cast<int64_t>(rhs));
432*635a8641SAndroid Build Coastguard Worker return true;
433*635a8641SAndroid Build Coastguard Worker case OP_NEGATE:
434*635a8641SAndroid Build Coastguard Worker *num = -lhs;
435*635a8641SAndroid Build Coastguard Worker return true;
436*635a8641SAndroid Build Coastguard Worker default:
437*635a8641SAndroid Build Coastguard Worker NOTREACHED();
438*635a8641SAndroid Build Coastguard Worker return false;
439*635a8641SAndroid Build Coastguard Worker }
440*635a8641SAndroid Build Coastguard Worker }
441*635a8641SAndroid Build Coastguard Worker
GetAsDouble(const TraceEvent & event,double * num) const442*635a8641SAndroid Build Coastguard Worker bool Query::GetAsDouble(const TraceEvent& event, double* num) const {
443*635a8641SAndroid Build Coastguard Worker switch (type_) {
444*635a8641SAndroid Build Coastguard Worker case QUERY_ARITHMETIC_OPERATOR:
445*635a8641SAndroid Build Coastguard Worker return EvaluateArithmeticOperator(event, num);
446*635a8641SAndroid Build Coastguard Worker case QUERY_EVENT_MEMBER:
447*635a8641SAndroid Build Coastguard Worker return GetMemberValueAsDouble(event, num);
448*635a8641SAndroid Build Coastguard Worker case QUERY_NUMBER:
449*635a8641SAndroid Build Coastguard Worker *num = number_;
450*635a8641SAndroid Build Coastguard Worker return true;
451*635a8641SAndroid Build Coastguard Worker default:
452*635a8641SAndroid Build Coastguard Worker return false;
453*635a8641SAndroid Build Coastguard Worker }
454*635a8641SAndroid Build Coastguard Worker }
455*635a8641SAndroid Build Coastguard Worker
GetAsString(const TraceEvent & event,std::string * str) const456*635a8641SAndroid Build Coastguard Worker bool Query::GetAsString(const TraceEvent& event, std::string* str) const {
457*635a8641SAndroid Build Coastguard Worker switch (type_) {
458*635a8641SAndroid Build Coastguard Worker case QUERY_EVENT_MEMBER:
459*635a8641SAndroid Build Coastguard Worker return GetMemberValueAsString(event, str);
460*635a8641SAndroid Build Coastguard Worker case QUERY_STRING:
461*635a8641SAndroid Build Coastguard Worker *str = string_;
462*635a8641SAndroid Build Coastguard Worker return true;
463*635a8641SAndroid Build Coastguard Worker default:
464*635a8641SAndroid Build Coastguard Worker return false;
465*635a8641SAndroid Build Coastguard Worker }
466*635a8641SAndroid Build Coastguard Worker }
467*635a8641SAndroid Build Coastguard Worker
SelectTargetEvent(const TraceEvent * event,TraceEventMember member)468*635a8641SAndroid Build Coastguard Worker const TraceEvent* Query::SelectTargetEvent(const TraceEvent* event,
469*635a8641SAndroid Build Coastguard Worker TraceEventMember member) {
470*635a8641SAndroid Build Coastguard Worker if (member >= OTHER_FIRST_MEMBER && member <= OTHER_LAST_MEMBER) {
471*635a8641SAndroid Build Coastguard Worker return event->other_event;
472*635a8641SAndroid Build Coastguard Worker } else if (member >= PREV_FIRST_MEMBER && member <= PREV_LAST_MEMBER) {
473*635a8641SAndroid Build Coastguard Worker return event->prev_event;
474*635a8641SAndroid Build Coastguard Worker } else {
475*635a8641SAndroid Build Coastguard Worker return event;
476*635a8641SAndroid Build Coastguard Worker }
477*635a8641SAndroid Build Coastguard Worker }
478*635a8641SAndroid Build Coastguard Worker
GetMemberValueAsDouble(const TraceEvent & event,double * num) const479*635a8641SAndroid Build Coastguard Worker bool Query::GetMemberValueAsDouble(const TraceEvent& event,
480*635a8641SAndroid Build Coastguard Worker double* num) const {
481*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(QUERY_EVENT_MEMBER, type_);
482*635a8641SAndroid Build Coastguard Worker
483*635a8641SAndroid Build Coastguard Worker // This could be a request for a member of |event| or a member of |event|'s
484*635a8641SAndroid Build Coastguard Worker // associated previous or next event. Store the target event in the_event:
485*635a8641SAndroid Build Coastguard Worker const TraceEvent* the_event = SelectTargetEvent(&event, member_);
486*635a8641SAndroid Build Coastguard Worker
487*635a8641SAndroid Build Coastguard Worker // Request for member of associated event, but there is no associated event.
488*635a8641SAndroid Build Coastguard Worker if (!the_event)
489*635a8641SAndroid Build Coastguard Worker return false;
490*635a8641SAndroid Build Coastguard Worker
491*635a8641SAndroid Build Coastguard Worker switch (member_) {
492*635a8641SAndroid Build Coastguard Worker case EVENT_PID:
493*635a8641SAndroid Build Coastguard Worker case OTHER_PID:
494*635a8641SAndroid Build Coastguard Worker case PREV_PID:
495*635a8641SAndroid Build Coastguard Worker *num = static_cast<double>(the_event->thread.process_id);
496*635a8641SAndroid Build Coastguard Worker return true;
497*635a8641SAndroid Build Coastguard Worker case EVENT_TID:
498*635a8641SAndroid Build Coastguard Worker case OTHER_TID:
499*635a8641SAndroid Build Coastguard Worker case PREV_TID:
500*635a8641SAndroid Build Coastguard Worker *num = static_cast<double>(the_event->thread.thread_id);
501*635a8641SAndroid Build Coastguard Worker return true;
502*635a8641SAndroid Build Coastguard Worker case EVENT_TIME:
503*635a8641SAndroid Build Coastguard Worker case OTHER_TIME:
504*635a8641SAndroid Build Coastguard Worker case PREV_TIME:
505*635a8641SAndroid Build Coastguard Worker *num = the_event->timestamp;
506*635a8641SAndroid Build Coastguard Worker return true;
507*635a8641SAndroid Build Coastguard Worker case EVENT_DURATION:
508*635a8641SAndroid Build Coastguard Worker if (!the_event->has_other_event())
509*635a8641SAndroid Build Coastguard Worker return false;
510*635a8641SAndroid Build Coastguard Worker *num = the_event->GetAbsTimeToOtherEvent();
511*635a8641SAndroid Build Coastguard Worker return true;
512*635a8641SAndroid Build Coastguard Worker case EVENT_COMPLETE_DURATION:
513*635a8641SAndroid Build Coastguard Worker if (the_event->phase != TRACE_EVENT_PHASE_COMPLETE)
514*635a8641SAndroid Build Coastguard Worker return false;
515*635a8641SAndroid Build Coastguard Worker *num = the_event->duration;
516*635a8641SAndroid Build Coastguard Worker return true;
517*635a8641SAndroid Build Coastguard Worker case EVENT_PHASE:
518*635a8641SAndroid Build Coastguard Worker case OTHER_PHASE:
519*635a8641SAndroid Build Coastguard Worker case PREV_PHASE:
520*635a8641SAndroid Build Coastguard Worker *num = static_cast<double>(the_event->phase);
521*635a8641SAndroid Build Coastguard Worker return true;
522*635a8641SAndroid Build Coastguard Worker case EVENT_HAS_STRING_ARG:
523*635a8641SAndroid Build Coastguard Worker case OTHER_HAS_STRING_ARG:
524*635a8641SAndroid Build Coastguard Worker case PREV_HAS_STRING_ARG:
525*635a8641SAndroid Build Coastguard Worker *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0);
526*635a8641SAndroid Build Coastguard Worker return true;
527*635a8641SAndroid Build Coastguard Worker case EVENT_HAS_NUMBER_ARG:
528*635a8641SAndroid Build Coastguard Worker case OTHER_HAS_NUMBER_ARG:
529*635a8641SAndroid Build Coastguard Worker case PREV_HAS_NUMBER_ARG:
530*635a8641SAndroid Build Coastguard Worker *num = (the_event->HasNumberArg(string_) ? 1.0 : 0.0);
531*635a8641SAndroid Build Coastguard Worker return true;
532*635a8641SAndroid Build Coastguard Worker case EVENT_ARG:
533*635a8641SAndroid Build Coastguard Worker case OTHER_ARG:
534*635a8641SAndroid Build Coastguard Worker case PREV_ARG: {
535*635a8641SAndroid Build Coastguard Worker // Search for the argument name and return its value if found.
536*635a8641SAndroid Build Coastguard Worker std::map<std::string, double>::const_iterator num_i =
537*635a8641SAndroid Build Coastguard Worker the_event->arg_numbers.find(string_);
538*635a8641SAndroid Build Coastguard Worker if (num_i == the_event->arg_numbers.end())
539*635a8641SAndroid Build Coastguard Worker return false;
540*635a8641SAndroid Build Coastguard Worker *num = num_i->second;
541*635a8641SAndroid Build Coastguard Worker return true;
542*635a8641SAndroid Build Coastguard Worker }
543*635a8641SAndroid Build Coastguard Worker case EVENT_HAS_OTHER:
544*635a8641SAndroid Build Coastguard Worker // return 1.0 (true) if the other event exists
545*635a8641SAndroid Build Coastguard Worker *num = event.other_event ? 1.0 : 0.0;
546*635a8641SAndroid Build Coastguard Worker return true;
547*635a8641SAndroid Build Coastguard Worker case EVENT_HAS_PREV:
548*635a8641SAndroid Build Coastguard Worker *num = event.prev_event ? 1.0 : 0.0;
549*635a8641SAndroid Build Coastguard Worker return true;
550*635a8641SAndroid Build Coastguard Worker default:
551*635a8641SAndroid Build Coastguard Worker return false;
552*635a8641SAndroid Build Coastguard Worker }
553*635a8641SAndroid Build Coastguard Worker }
554*635a8641SAndroid Build Coastguard Worker
GetMemberValueAsString(const TraceEvent & event,std::string * str) const555*635a8641SAndroid Build Coastguard Worker bool Query::GetMemberValueAsString(const TraceEvent& event,
556*635a8641SAndroid Build Coastguard Worker std::string* str) const {
557*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(QUERY_EVENT_MEMBER, type_);
558*635a8641SAndroid Build Coastguard Worker
559*635a8641SAndroid Build Coastguard Worker // This could be a request for a member of |event| or a member of |event|'s
560*635a8641SAndroid Build Coastguard Worker // associated previous or next event. Store the target event in the_event:
561*635a8641SAndroid Build Coastguard Worker const TraceEvent* the_event = SelectTargetEvent(&event, member_);
562*635a8641SAndroid Build Coastguard Worker
563*635a8641SAndroid Build Coastguard Worker // Request for member of associated event, but there is no associated event.
564*635a8641SAndroid Build Coastguard Worker if (!the_event)
565*635a8641SAndroid Build Coastguard Worker return false;
566*635a8641SAndroid Build Coastguard Worker
567*635a8641SAndroid Build Coastguard Worker switch (member_) {
568*635a8641SAndroid Build Coastguard Worker case EVENT_CATEGORY:
569*635a8641SAndroid Build Coastguard Worker case OTHER_CATEGORY:
570*635a8641SAndroid Build Coastguard Worker case PREV_CATEGORY:
571*635a8641SAndroid Build Coastguard Worker *str = the_event->category;
572*635a8641SAndroid Build Coastguard Worker return true;
573*635a8641SAndroid Build Coastguard Worker case EVENT_NAME:
574*635a8641SAndroid Build Coastguard Worker case OTHER_NAME:
575*635a8641SAndroid Build Coastguard Worker case PREV_NAME:
576*635a8641SAndroid Build Coastguard Worker *str = the_event->name;
577*635a8641SAndroid Build Coastguard Worker return true;
578*635a8641SAndroid Build Coastguard Worker case EVENT_ID:
579*635a8641SAndroid Build Coastguard Worker case OTHER_ID:
580*635a8641SAndroid Build Coastguard Worker case PREV_ID:
581*635a8641SAndroid Build Coastguard Worker *str = the_event->id;
582*635a8641SAndroid Build Coastguard Worker return true;
583*635a8641SAndroid Build Coastguard Worker case EVENT_ARG:
584*635a8641SAndroid Build Coastguard Worker case OTHER_ARG:
585*635a8641SAndroid Build Coastguard Worker case PREV_ARG: {
586*635a8641SAndroid Build Coastguard Worker // Search for the argument name and return its value if found.
587*635a8641SAndroid Build Coastguard Worker std::map<std::string, std::string>::const_iterator str_i =
588*635a8641SAndroid Build Coastguard Worker the_event->arg_strings.find(string_);
589*635a8641SAndroid Build Coastguard Worker if (str_i == the_event->arg_strings.end())
590*635a8641SAndroid Build Coastguard Worker return false;
591*635a8641SAndroid Build Coastguard Worker *str = str_i->second;
592*635a8641SAndroid Build Coastguard Worker return true;
593*635a8641SAndroid Build Coastguard Worker }
594*635a8641SAndroid Build Coastguard Worker default:
595*635a8641SAndroid Build Coastguard Worker return false;
596*635a8641SAndroid Build Coastguard Worker }
597*635a8641SAndroid Build Coastguard Worker }
598*635a8641SAndroid Build Coastguard Worker
Query(const std::string & str)599*635a8641SAndroid Build Coastguard Worker Query::Query(const std::string& str)
600*635a8641SAndroid Build Coastguard Worker : type_(QUERY_STRING),
601*635a8641SAndroid Build Coastguard Worker operator_(OP_INVALID),
602*635a8641SAndroid Build Coastguard Worker member_(EVENT_INVALID),
603*635a8641SAndroid Build Coastguard Worker number_(0),
604*635a8641SAndroid Build Coastguard Worker string_(str),
605*635a8641SAndroid Build Coastguard Worker is_pattern_(false) {
606*635a8641SAndroid Build Coastguard Worker }
607*635a8641SAndroid Build Coastguard Worker
Query(double num)608*635a8641SAndroid Build Coastguard Worker Query::Query(double num)
609*635a8641SAndroid Build Coastguard Worker : type_(QUERY_NUMBER),
610*635a8641SAndroid Build Coastguard Worker operator_(OP_INVALID),
611*635a8641SAndroid Build Coastguard Worker member_(EVENT_INVALID),
612*635a8641SAndroid Build Coastguard Worker number_(num),
613*635a8641SAndroid Build Coastguard Worker is_pattern_(false) {
614*635a8641SAndroid Build Coastguard Worker }
left() const615*635a8641SAndroid Build Coastguard Worker const Query& Query::left() const {
616*635a8641SAndroid Build Coastguard Worker return left_->query();
617*635a8641SAndroid Build Coastguard Worker }
618*635a8641SAndroid Build Coastguard Worker
right() const619*635a8641SAndroid Build Coastguard Worker const Query& Query::right() const {
620*635a8641SAndroid Build Coastguard Worker return right_->query();
621*635a8641SAndroid Build Coastguard Worker }
622*635a8641SAndroid Build Coastguard Worker
operator ==(const Query & rhs) const623*635a8641SAndroid Build Coastguard Worker Query Query::operator==(const Query& rhs) const {
624*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_EQ);
625*635a8641SAndroid Build Coastguard Worker }
626*635a8641SAndroid Build Coastguard Worker
operator !=(const Query & rhs) const627*635a8641SAndroid Build Coastguard Worker Query Query::operator!=(const Query& rhs) const {
628*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_NE);
629*635a8641SAndroid Build Coastguard Worker }
630*635a8641SAndroid Build Coastguard Worker
operator <(const Query & rhs) const631*635a8641SAndroid Build Coastguard Worker Query Query::operator<(const Query& rhs) const {
632*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_LT);
633*635a8641SAndroid Build Coastguard Worker }
634*635a8641SAndroid Build Coastguard Worker
operator <=(const Query & rhs) const635*635a8641SAndroid Build Coastguard Worker Query Query::operator<=(const Query& rhs) const {
636*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_LE);
637*635a8641SAndroid Build Coastguard Worker }
638*635a8641SAndroid Build Coastguard Worker
operator >(const Query & rhs) const639*635a8641SAndroid Build Coastguard Worker Query Query::operator>(const Query& rhs) const {
640*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_GT);
641*635a8641SAndroid Build Coastguard Worker }
642*635a8641SAndroid Build Coastguard Worker
operator >=(const Query & rhs) const643*635a8641SAndroid Build Coastguard Worker Query Query::operator>=(const Query& rhs) const {
644*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_GE);
645*635a8641SAndroid Build Coastguard Worker }
646*635a8641SAndroid Build Coastguard Worker
operator &&(const Query & rhs) const647*635a8641SAndroid Build Coastguard Worker Query Query::operator&&(const Query& rhs) const {
648*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_AND);
649*635a8641SAndroid Build Coastguard Worker }
650*635a8641SAndroid Build Coastguard Worker
operator ||(const Query & rhs) const651*635a8641SAndroid Build Coastguard Worker Query Query::operator||(const Query& rhs) const {
652*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_OR);
653*635a8641SAndroid Build Coastguard Worker }
654*635a8641SAndroid Build Coastguard Worker
operator !() const655*635a8641SAndroid Build Coastguard Worker Query Query::operator!() const {
656*635a8641SAndroid Build Coastguard Worker return Query(*this, OP_NOT);
657*635a8641SAndroid Build Coastguard Worker }
658*635a8641SAndroid Build Coastguard Worker
operator +(const Query & rhs) const659*635a8641SAndroid Build Coastguard Worker Query Query::operator+(const Query& rhs) const {
660*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_ADD);
661*635a8641SAndroid Build Coastguard Worker }
662*635a8641SAndroid Build Coastguard Worker
operator -(const Query & rhs) const663*635a8641SAndroid Build Coastguard Worker Query Query::operator-(const Query& rhs) const {
664*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_SUB);
665*635a8641SAndroid Build Coastguard Worker }
666*635a8641SAndroid Build Coastguard Worker
operator *(const Query & rhs) const667*635a8641SAndroid Build Coastguard Worker Query Query::operator*(const Query& rhs) const {
668*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_MUL);
669*635a8641SAndroid Build Coastguard Worker }
670*635a8641SAndroid Build Coastguard Worker
operator /(const Query & rhs) const671*635a8641SAndroid Build Coastguard Worker Query Query::operator/(const Query& rhs) const {
672*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_DIV);
673*635a8641SAndroid Build Coastguard Worker }
674*635a8641SAndroid Build Coastguard Worker
operator %(const Query & rhs) const675*635a8641SAndroid Build Coastguard Worker Query Query::operator%(const Query& rhs) const {
676*635a8641SAndroid Build Coastguard Worker return Query(*this, rhs, OP_MOD);
677*635a8641SAndroid Build Coastguard Worker }
678*635a8641SAndroid Build Coastguard Worker
operator -() const679*635a8641SAndroid Build Coastguard Worker Query Query::operator-() const {
680*635a8641SAndroid Build Coastguard Worker return Query(*this, OP_NEGATE);
681*635a8641SAndroid Build Coastguard Worker }
682*635a8641SAndroid Build Coastguard Worker
683*635a8641SAndroid Build Coastguard Worker
Query(const Query & left,const Query & right,Operator binary_op)684*635a8641SAndroid Build Coastguard Worker Query::Query(const Query& left, const Query& right, Operator binary_op)
685*635a8641SAndroid Build Coastguard Worker : operator_(binary_op),
686*635a8641SAndroid Build Coastguard Worker left_(new QueryNode(left)),
687*635a8641SAndroid Build Coastguard Worker right_(new QueryNode(right)),
688*635a8641SAndroid Build Coastguard Worker member_(EVENT_INVALID),
689*635a8641SAndroid Build Coastguard Worker number_(0) {
690*635a8641SAndroid Build Coastguard Worker type_ = (binary_op < OP_ADD ?
691*635a8641SAndroid Build Coastguard Worker QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
692*635a8641SAndroid Build Coastguard Worker }
693*635a8641SAndroid Build Coastguard Worker
Query(const Query & left,Operator unary_op)694*635a8641SAndroid Build Coastguard Worker Query::Query(const Query& left, Operator unary_op)
695*635a8641SAndroid Build Coastguard Worker : operator_(unary_op),
696*635a8641SAndroid Build Coastguard Worker left_(new QueryNode(left)),
697*635a8641SAndroid Build Coastguard Worker member_(EVENT_INVALID),
698*635a8641SAndroid Build Coastguard Worker number_(0) {
699*635a8641SAndroid Build Coastguard Worker type_ = (unary_op < OP_ADD ?
700*635a8641SAndroid Build Coastguard Worker QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
701*635a8641SAndroid Build Coastguard Worker }
702*635a8641SAndroid Build Coastguard Worker
703*635a8641SAndroid Build Coastguard Worker namespace {
704*635a8641SAndroid Build Coastguard Worker
705*635a8641SAndroid Build Coastguard Worker // Search |events| for |query| and add matches to |output|.
FindMatchingEvents(const std::vector<TraceEvent> & events,const Query & query,TraceEventVector * output,bool ignore_metadata_events)706*635a8641SAndroid Build Coastguard Worker size_t FindMatchingEvents(const std::vector<TraceEvent>& events,
707*635a8641SAndroid Build Coastguard Worker const Query& query,
708*635a8641SAndroid Build Coastguard Worker TraceEventVector* output,
709*635a8641SAndroid Build Coastguard Worker bool ignore_metadata_events) {
710*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < events.size(); ++i) {
711*635a8641SAndroid Build Coastguard Worker if (ignore_metadata_events && events[i].phase == TRACE_EVENT_PHASE_METADATA)
712*635a8641SAndroid Build Coastguard Worker continue;
713*635a8641SAndroid Build Coastguard Worker if (query.Evaluate(events[i]))
714*635a8641SAndroid Build Coastguard Worker output->push_back(&events[i]);
715*635a8641SAndroid Build Coastguard Worker }
716*635a8641SAndroid Build Coastguard Worker return output->size();
717*635a8641SAndroid Build Coastguard Worker }
718*635a8641SAndroid Build Coastguard Worker
ParseEventsFromJson(const std::string & json,std::vector<TraceEvent> * output)719*635a8641SAndroid Build Coastguard Worker bool ParseEventsFromJson(const std::string& json,
720*635a8641SAndroid Build Coastguard Worker std::vector<TraceEvent>* output) {
721*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::Value> root = base::JSONReader::Read(json);
722*635a8641SAndroid Build Coastguard Worker
723*635a8641SAndroid Build Coastguard Worker base::ListValue* root_list = nullptr;
724*635a8641SAndroid Build Coastguard Worker if (!root.get() || !root->GetAsList(&root_list))
725*635a8641SAndroid Build Coastguard Worker return false;
726*635a8641SAndroid Build Coastguard Worker
727*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < root_list->GetSize(); ++i) {
728*635a8641SAndroid Build Coastguard Worker base::Value* item = nullptr;
729*635a8641SAndroid Build Coastguard Worker if (root_list->Get(i, &item)) {
730*635a8641SAndroid Build Coastguard Worker TraceEvent event;
731*635a8641SAndroid Build Coastguard Worker if (event.SetFromJSON(item))
732*635a8641SAndroid Build Coastguard Worker output->push_back(std::move(event));
733*635a8641SAndroid Build Coastguard Worker else
734*635a8641SAndroid Build Coastguard Worker return false;
735*635a8641SAndroid Build Coastguard Worker }
736*635a8641SAndroid Build Coastguard Worker }
737*635a8641SAndroid Build Coastguard Worker
738*635a8641SAndroid Build Coastguard Worker return true;
739*635a8641SAndroid Build Coastguard Worker }
740*635a8641SAndroid Build Coastguard Worker
741*635a8641SAndroid Build Coastguard Worker } // namespace
742*635a8641SAndroid Build Coastguard Worker
743*635a8641SAndroid Build Coastguard Worker // TraceAnalyzer
744*635a8641SAndroid Build Coastguard Worker
TraceAnalyzer()745*635a8641SAndroid Build Coastguard Worker TraceAnalyzer::TraceAnalyzer()
746*635a8641SAndroid Build Coastguard Worker : ignore_metadata_events_(false), allow_association_changes_(true) {}
747*635a8641SAndroid Build Coastguard Worker
748*635a8641SAndroid Build Coastguard Worker TraceAnalyzer::~TraceAnalyzer() = default;
749*635a8641SAndroid Build Coastguard Worker
750*635a8641SAndroid Build Coastguard Worker // static
Create(const std::string & json_events)751*635a8641SAndroid Build Coastguard Worker TraceAnalyzer* TraceAnalyzer::Create(const std::string& json_events) {
752*635a8641SAndroid Build Coastguard Worker std::unique_ptr<TraceAnalyzer> analyzer(new TraceAnalyzer());
753*635a8641SAndroid Build Coastguard Worker if (analyzer->SetEvents(json_events))
754*635a8641SAndroid Build Coastguard Worker return analyzer.release();
755*635a8641SAndroid Build Coastguard Worker return nullptr;
756*635a8641SAndroid Build Coastguard Worker }
757*635a8641SAndroid Build Coastguard Worker
SetEvents(const std::string & json_events)758*635a8641SAndroid Build Coastguard Worker bool TraceAnalyzer::SetEvents(const std::string& json_events) {
759*635a8641SAndroid Build Coastguard Worker raw_events_.clear();
760*635a8641SAndroid Build Coastguard Worker if (!ParseEventsFromJson(json_events, &raw_events_))
761*635a8641SAndroid Build Coastguard Worker return false;
762*635a8641SAndroid Build Coastguard Worker std::stable_sort(raw_events_.begin(), raw_events_.end());
763*635a8641SAndroid Build Coastguard Worker ParseMetadata();
764*635a8641SAndroid Build Coastguard Worker return true;
765*635a8641SAndroid Build Coastguard Worker }
766*635a8641SAndroid Build Coastguard Worker
AssociateBeginEndEvents()767*635a8641SAndroid Build Coastguard Worker void TraceAnalyzer::AssociateBeginEndEvents() {
768*635a8641SAndroid Build Coastguard Worker using trace_analyzer::Query;
769*635a8641SAndroid Build Coastguard Worker
770*635a8641SAndroid Build Coastguard Worker Query begin(Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN));
771*635a8641SAndroid Build Coastguard Worker Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_END));
772*635a8641SAndroid Build Coastguard Worker Query match(Query::EventName() == Query::OtherName() &&
773*635a8641SAndroid Build Coastguard Worker Query::EventCategory() == Query::OtherCategory() &&
774*635a8641SAndroid Build Coastguard Worker Query::EventTid() == Query::OtherTid() &&
775*635a8641SAndroid Build Coastguard Worker Query::EventPid() == Query::OtherPid());
776*635a8641SAndroid Build Coastguard Worker
777*635a8641SAndroid Build Coastguard Worker AssociateEvents(begin, end, match);
778*635a8641SAndroid Build Coastguard Worker }
779*635a8641SAndroid Build Coastguard Worker
AssociateAsyncBeginEndEvents(bool match_pid)780*635a8641SAndroid Build Coastguard Worker void TraceAnalyzer::AssociateAsyncBeginEndEvents(bool match_pid) {
781*635a8641SAndroid Build Coastguard Worker using trace_analyzer::Query;
782*635a8641SAndroid Build Coastguard Worker
783*635a8641SAndroid Build Coastguard Worker Query begin(
784*635a8641SAndroid Build Coastguard Worker Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) ||
785*635a8641SAndroid Build Coastguard Worker Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
786*635a8641SAndroid Build Coastguard Worker Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
787*635a8641SAndroid Build Coastguard Worker Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_END) ||
788*635a8641SAndroid Build Coastguard Worker Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
789*635a8641SAndroid Build Coastguard Worker Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
790*635a8641SAndroid Build Coastguard Worker Query match(Query::EventCategory() == Query::OtherCategory() &&
791*635a8641SAndroid Build Coastguard Worker Query::EventId() == Query::OtherId());
792*635a8641SAndroid Build Coastguard Worker
793*635a8641SAndroid Build Coastguard Worker if (match_pid) {
794*635a8641SAndroid Build Coastguard Worker match = match && Query::EventPid() == Query::OtherPid();
795*635a8641SAndroid Build Coastguard Worker }
796*635a8641SAndroid Build Coastguard Worker
797*635a8641SAndroid Build Coastguard Worker AssociateEvents(begin, end, match);
798*635a8641SAndroid Build Coastguard Worker }
799*635a8641SAndroid Build Coastguard Worker
AssociateEvents(const Query & first,const Query & second,const Query & match)800*635a8641SAndroid Build Coastguard Worker void TraceAnalyzer::AssociateEvents(const Query& first,
801*635a8641SAndroid Build Coastguard Worker const Query& second,
802*635a8641SAndroid Build Coastguard Worker const Query& match) {
803*635a8641SAndroid Build Coastguard Worker DCHECK(allow_association_changes_)
804*635a8641SAndroid Build Coastguard Worker << "AssociateEvents not allowed after FindEvents";
805*635a8641SAndroid Build Coastguard Worker
806*635a8641SAndroid Build Coastguard Worker // Search for matching begin/end event pairs. When a matching end is found,
807*635a8641SAndroid Build Coastguard Worker // it is associated with the begin event.
808*635a8641SAndroid Build Coastguard Worker std::vector<TraceEvent*> begin_stack;
809*635a8641SAndroid Build Coastguard Worker for (size_t event_index = 0; event_index < raw_events_.size();
810*635a8641SAndroid Build Coastguard Worker ++event_index) {
811*635a8641SAndroid Build Coastguard Worker
812*635a8641SAndroid Build Coastguard Worker TraceEvent& this_event = raw_events_[event_index];
813*635a8641SAndroid Build Coastguard Worker
814*635a8641SAndroid Build Coastguard Worker if (second.Evaluate(this_event)) {
815*635a8641SAndroid Build Coastguard Worker // Search stack for matching begin, starting from end.
816*635a8641SAndroid Build Coastguard Worker for (int stack_index = static_cast<int>(begin_stack.size()) - 1;
817*635a8641SAndroid Build Coastguard Worker stack_index >= 0; --stack_index) {
818*635a8641SAndroid Build Coastguard Worker TraceEvent& begin_event = *begin_stack[stack_index];
819*635a8641SAndroid Build Coastguard Worker
820*635a8641SAndroid Build Coastguard Worker // Temporarily set other to test against the match query.
821*635a8641SAndroid Build Coastguard Worker const TraceEvent* other_backup = begin_event.other_event;
822*635a8641SAndroid Build Coastguard Worker begin_event.other_event = &this_event;
823*635a8641SAndroid Build Coastguard Worker if (match.Evaluate(begin_event)) {
824*635a8641SAndroid Build Coastguard Worker // Found a matching begin/end pair.
825*635a8641SAndroid Build Coastguard Worker // Set the associated previous event
826*635a8641SAndroid Build Coastguard Worker this_event.prev_event = &begin_event;
827*635a8641SAndroid Build Coastguard Worker // Erase the matching begin event index from the stack.
828*635a8641SAndroid Build Coastguard Worker begin_stack.erase(begin_stack.begin() + stack_index);
829*635a8641SAndroid Build Coastguard Worker break;
830*635a8641SAndroid Build Coastguard Worker }
831*635a8641SAndroid Build Coastguard Worker
832*635a8641SAndroid Build Coastguard Worker // Not a match, restore original other and continue.
833*635a8641SAndroid Build Coastguard Worker begin_event.other_event = other_backup;
834*635a8641SAndroid Build Coastguard Worker }
835*635a8641SAndroid Build Coastguard Worker }
836*635a8641SAndroid Build Coastguard Worker // Even if this_event is a |second| event that has matched an earlier
837*635a8641SAndroid Build Coastguard Worker // |first| event, it can still also be a |first| event and be associated
838*635a8641SAndroid Build Coastguard Worker // with a later |second| event.
839*635a8641SAndroid Build Coastguard Worker if (first.Evaluate(this_event)) {
840*635a8641SAndroid Build Coastguard Worker begin_stack.push_back(&this_event);
841*635a8641SAndroid Build Coastguard Worker }
842*635a8641SAndroid Build Coastguard Worker }
843*635a8641SAndroid Build Coastguard Worker }
844*635a8641SAndroid Build Coastguard Worker
MergeAssociatedEventArgs()845*635a8641SAndroid Build Coastguard Worker void TraceAnalyzer::MergeAssociatedEventArgs() {
846*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < raw_events_.size(); ++i) {
847*635a8641SAndroid Build Coastguard Worker // Merge all associated events with the first event.
848*635a8641SAndroid Build Coastguard Worker const TraceEvent* other = raw_events_[i].other_event;
849*635a8641SAndroid Build Coastguard Worker // Avoid looping by keeping set of encountered TraceEvents.
850*635a8641SAndroid Build Coastguard Worker std::set<const TraceEvent*> encounters;
851*635a8641SAndroid Build Coastguard Worker encounters.insert(&raw_events_[i]);
852*635a8641SAndroid Build Coastguard Worker while (other && encounters.find(other) == encounters.end()) {
853*635a8641SAndroid Build Coastguard Worker encounters.insert(other);
854*635a8641SAndroid Build Coastguard Worker raw_events_[i].arg_numbers.insert(
855*635a8641SAndroid Build Coastguard Worker other->arg_numbers.begin(),
856*635a8641SAndroid Build Coastguard Worker other->arg_numbers.end());
857*635a8641SAndroid Build Coastguard Worker raw_events_[i].arg_strings.insert(
858*635a8641SAndroid Build Coastguard Worker other->arg_strings.begin(),
859*635a8641SAndroid Build Coastguard Worker other->arg_strings.end());
860*635a8641SAndroid Build Coastguard Worker other = other->other_event;
861*635a8641SAndroid Build Coastguard Worker }
862*635a8641SAndroid Build Coastguard Worker }
863*635a8641SAndroid Build Coastguard Worker }
864*635a8641SAndroid Build Coastguard Worker
FindEvents(const Query & query,TraceEventVector * output)865*635a8641SAndroid Build Coastguard Worker size_t TraceAnalyzer::FindEvents(const Query& query, TraceEventVector* output) {
866*635a8641SAndroid Build Coastguard Worker allow_association_changes_ = false;
867*635a8641SAndroid Build Coastguard Worker output->clear();
868*635a8641SAndroid Build Coastguard Worker return FindMatchingEvents(
869*635a8641SAndroid Build Coastguard Worker raw_events_, query, output, ignore_metadata_events_);
870*635a8641SAndroid Build Coastguard Worker }
871*635a8641SAndroid Build Coastguard Worker
FindFirstOf(const Query & query)872*635a8641SAndroid Build Coastguard Worker const TraceEvent* TraceAnalyzer::FindFirstOf(const Query& query) {
873*635a8641SAndroid Build Coastguard Worker TraceEventVector output;
874*635a8641SAndroid Build Coastguard Worker if (FindEvents(query, &output) > 0)
875*635a8641SAndroid Build Coastguard Worker return output.front();
876*635a8641SAndroid Build Coastguard Worker return nullptr;
877*635a8641SAndroid Build Coastguard Worker }
878*635a8641SAndroid Build Coastguard Worker
FindLastOf(const Query & query)879*635a8641SAndroid Build Coastguard Worker const TraceEvent* TraceAnalyzer::FindLastOf(const Query& query) {
880*635a8641SAndroid Build Coastguard Worker TraceEventVector output;
881*635a8641SAndroid Build Coastguard Worker if (FindEvents(query, &output) > 0)
882*635a8641SAndroid Build Coastguard Worker return output.back();
883*635a8641SAndroid Build Coastguard Worker return nullptr;
884*635a8641SAndroid Build Coastguard Worker }
885*635a8641SAndroid Build Coastguard Worker
GetThreadName(const TraceEvent::ProcessThreadID & thread)886*635a8641SAndroid Build Coastguard Worker const std::string& TraceAnalyzer::GetThreadName(
887*635a8641SAndroid Build Coastguard Worker const TraceEvent::ProcessThreadID& thread) {
888*635a8641SAndroid Build Coastguard Worker // If thread is not found, just add and return empty string.
889*635a8641SAndroid Build Coastguard Worker return thread_names_[thread];
890*635a8641SAndroid Build Coastguard Worker }
891*635a8641SAndroid Build Coastguard Worker
ParseMetadata()892*635a8641SAndroid Build Coastguard Worker void TraceAnalyzer::ParseMetadata() {
893*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < raw_events_.size(); ++i) {
894*635a8641SAndroid Build Coastguard Worker TraceEvent& this_event = raw_events_[i];
895*635a8641SAndroid Build Coastguard Worker // Check for thread name metadata.
896*635a8641SAndroid Build Coastguard Worker if (this_event.phase != TRACE_EVENT_PHASE_METADATA ||
897*635a8641SAndroid Build Coastguard Worker this_event.name != "thread_name")
898*635a8641SAndroid Build Coastguard Worker continue;
899*635a8641SAndroid Build Coastguard Worker std::map<std::string, std::string>::const_iterator string_it =
900*635a8641SAndroid Build Coastguard Worker this_event.arg_strings.find("name");
901*635a8641SAndroid Build Coastguard Worker if (string_it != this_event.arg_strings.end())
902*635a8641SAndroid Build Coastguard Worker thread_names_[this_event.thread] = string_it->second;
903*635a8641SAndroid Build Coastguard Worker }
904*635a8641SAndroid Build Coastguard Worker }
905*635a8641SAndroid Build Coastguard Worker
906*635a8641SAndroid Build Coastguard Worker // Utility functions for collecting process-local traces and creating a
907*635a8641SAndroid Build Coastguard Worker // |TraceAnalyzer| from the result.
908*635a8641SAndroid Build Coastguard Worker
Start(const std::string & category_filter_string)909*635a8641SAndroid Build Coastguard Worker void Start(const std::string& category_filter_string) {
910*635a8641SAndroid Build Coastguard Worker DCHECK(!base::trace_event::TraceLog::GetInstance()->IsEnabled());
911*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceLog::GetInstance()->SetEnabled(
912*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceConfig(category_filter_string, ""),
913*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceLog::RECORDING_MODE);
914*635a8641SAndroid Build Coastguard Worker }
915*635a8641SAndroid Build Coastguard Worker
Stop()916*635a8641SAndroid Build Coastguard Worker std::unique_ptr<TraceAnalyzer> Stop() {
917*635a8641SAndroid Build Coastguard Worker DCHECK(base::trace_event::TraceLog::GetInstance()->IsEnabled());
918*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceLog::GetInstance()->SetDisabled();
919*635a8641SAndroid Build Coastguard Worker
920*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceResultBuffer buffer;
921*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceResultBuffer::SimpleOutput trace_output;
922*635a8641SAndroid Build Coastguard Worker buffer.SetOutputCallback(trace_output.GetCallback());
923*635a8641SAndroid Build Coastguard Worker base::RunLoop run_loop;
924*635a8641SAndroid Build Coastguard Worker buffer.Start();
925*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceLog::GetInstance()->Flush(
926*635a8641SAndroid Build Coastguard Worker base::BindRepeating(&OnTraceDataCollected, run_loop.QuitClosure(),
927*635a8641SAndroid Build Coastguard Worker base::Unretained(&buffer)));
928*635a8641SAndroid Build Coastguard Worker run_loop.Run();
929*635a8641SAndroid Build Coastguard Worker buffer.Finish();
930*635a8641SAndroid Build Coastguard Worker
931*635a8641SAndroid Build Coastguard Worker return base::WrapUnique(TraceAnalyzer::Create(trace_output.json_output));
932*635a8641SAndroid Build Coastguard Worker }
933*635a8641SAndroid Build Coastguard Worker
934*635a8641SAndroid Build Coastguard Worker // TraceEventVector utility functions.
935*635a8641SAndroid Build Coastguard Worker
GetRateStats(const TraceEventVector & events,RateStats * stats,const RateStatsOptions * options)936*635a8641SAndroid Build Coastguard Worker bool GetRateStats(const TraceEventVector& events,
937*635a8641SAndroid Build Coastguard Worker RateStats* stats,
938*635a8641SAndroid Build Coastguard Worker const RateStatsOptions* options) {
939*635a8641SAndroid Build Coastguard Worker DCHECK(stats);
940*635a8641SAndroid Build Coastguard Worker // Need at least 3 events to calculate rate stats.
941*635a8641SAndroid Build Coastguard Worker const size_t kMinEvents = 3;
942*635a8641SAndroid Build Coastguard Worker if (events.size() < kMinEvents) {
943*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Not enough events: " << events.size();
944*635a8641SAndroid Build Coastguard Worker return false;
945*635a8641SAndroid Build Coastguard Worker }
946*635a8641SAndroid Build Coastguard Worker
947*635a8641SAndroid Build Coastguard Worker std::vector<double> deltas;
948*635a8641SAndroid Build Coastguard Worker size_t num_deltas = events.size() - 1;
949*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < num_deltas; ++i) {
950*635a8641SAndroid Build Coastguard Worker double delta = events.at(i + 1)->timestamp - events.at(i)->timestamp;
951*635a8641SAndroid Build Coastguard Worker if (delta < 0.0) {
952*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Events are out of order";
953*635a8641SAndroid Build Coastguard Worker return false;
954*635a8641SAndroid Build Coastguard Worker }
955*635a8641SAndroid Build Coastguard Worker deltas.push_back(delta);
956*635a8641SAndroid Build Coastguard Worker }
957*635a8641SAndroid Build Coastguard Worker
958*635a8641SAndroid Build Coastguard Worker std::sort(deltas.begin(), deltas.end());
959*635a8641SAndroid Build Coastguard Worker
960*635a8641SAndroid Build Coastguard Worker if (options) {
961*635a8641SAndroid Build Coastguard Worker if (options->trim_min + options->trim_max > events.size() - kMinEvents) {
962*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Attempt to trim too many events";
963*635a8641SAndroid Build Coastguard Worker return false;
964*635a8641SAndroid Build Coastguard Worker }
965*635a8641SAndroid Build Coastguard Worker deltas.erase(deltas.begin(), deltas.begin() + options->trim_min);
966*635a8641SAndroid Build Coastguard Worker deltas.erase(deltas.end() - options->trim_max, deltas.end());
967*635a8641SAndroid Build Coastguard Worker }
968*635a8641SAndroid Build Coastguard Worker
969*635a8641SAndroid Build Coastguard Worker num_deltas = deltas.size();
970*635a8641SAndroid Build Coastguard Worker double delta_sum = 0.0;
971*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < num_deltas; ++i)
972*635a8641SAndroid Build Coastguard Worker delta_sum += deltas[i];
973*635a8641SAndroid Build Coastguard Worker
974*635a8641SAndroid Build Coastguard Worker stats->min_us = *std::min_element(deltas.begin(), deltas.end());
975*635a8641SAndroid Build Coastguard Worker stats->max_us = *std::max_element(deltas.begin(), deltas.end());
976*635a8641SAndroid Build Coastguard Worker stats->mean_us = delta_sum / static_cast<double>(num_deltas);
977*635a8641SAndroid Build Coastguard Worker
978*635a8641SAndroid Build Coastguard Worker double sum_mean_offsets_squared = 0.0;
979*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < num_deltas; ++i) {
980*635a8641SAndroid Build Coastguard Worker double offset = fabs(deltas[i] - stats->mean_us);
981*635a8641SAndroid Build Coastguard Worker sum_mean_offsets_squared += offset * offset;
982*635a8641SAndroid Build Coastguard Worker }
983*635a8641SAndroid Build Coastguard Worker stats->standard_deviation_us =
984*635a8641SAndroid Build Coastguard Worker sqrt(sum_mean_offsets_squared / static_cast<double>(num_deltas - 1));
985*635a8641SAndroid Build Coastguard Worker
986*635a8641SAndroid Build Coastguard Worker return true;
987*635a8641SAndroid Build Coastguard Worker }
988*635a8641SAndroid Build Coastguard Worker
FindFirstOf(const TraceEventVector & events,const Query & query,size_t position,size_t * return_index)989*635a8641SAndroid Build Coastguard Worker bool FindFirstOf(const TraceEventVector& events,
990*635a8641SAndroid Build Coastguard Worker const Query& query,
991*635a8641SAndroid Build Coastguard Worker size_t position,
992*635a8641SAndroid Build Coastguard Worker size_t* return_index) {
993*635a8641SAndroid Build Coastguard Worker DCHECK(return_index);
994*635a8641SAndroid Build Coastguard Worker for (size_t i = position; i < events.size(); ++i) {
995*635a8641SAndroid Build Coastguard Worker if (query.Evaluate(*events[i])) {
996*635a8641SAndroid Build Coastguard Worker *return_index = i;
997*635a8641SAndroid Build Coastguard Worker return true;
998*635a8641SAndroid Build Coastguard Worker }
999*635a8641SAndroid Build Coastguard Worker }
1000*635a8641SAndroid Build Coastguard Worker return false;
1001*635a8641SAndroid Build Coastguard Worker }
1002*635a8641SAndroid Build Coastguard Worker
FindLastOf(const TraceEventVector & events,const Query & query,size_t position,size_t * return_index)1003*635a8641SAndroid Build Coastguard Worker bool FindLastOf(const TraceEventVector& events,
1004*635a8641SAndroid Build Coastguard Worker const Query& query,
1005*635a8641SAndroid Build Coastguard Worker size_t position,
1006*635a8641SAndroid Build Coastguard Worker size_t* return_index) {
1007*635a8641SAndroid Build Coastguard Worker DCHECK(return_index);
1008*635a8641SAndroid Build Coastguard Worker for (size_t i = std::min(position + 1, events.size()); i != 0; --i) {
1009*635a8641SAndroid Build Coastguard Worker if (query.Evaluate(*events[i - 1])) {
1010*635a8641SAndroid Build Coastguard Worker *return_index = i - 1;
1011*635a8641SAndroid Build Coastguard Worker return true;
1012*635a8641SAndroid Build Coastguard Worker }
1013*635a8641SAndroid Build Coastguard Worker }
1014*635a8641SAndroid Build Coastguard Worker return false;
1015*635a8641SAndroid Build Coastguard Worker }
1016*635a8641SAndroid Build Coastguard Worker
FindClosest(const TraceEventVector & events,const Query & query,size_t position,size_t * return_closest,size_t * return_second_closest)1017*635a8641SAndroid Build Coastguard Worker bool FindClosest(const TraceEventVector& events,
1018*635a8641SAndroid Build Coastguard Worker const Query& query,
1019*635a8641SAndroid Build Coastguard Worker size_t position,
1020*635a8641SAndroid Build Coastguard Worker size_t* return_closest,
1021*635a8641SAndroid Build Coastguard Worker size_t* return_second_closest) {
1022*635a8641SAndroid Build Coastguard Worker DCHECK(return_closest);
1023*635a8641SAndroid Build Coastguard Worker if (events.empty() || position >= events.size())
1024*635a8641SAndroid Build Coastguard Worker return false;
1025*635a8641SAndroid Build Coastguard Worker size_t closest = events.size();
1026*635a8641SAndroid Build Coastguard Worker size_t second_closest = events.size();
1027*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < events.size(); ++i) {
1028*635a8641SAndroid Build Coastguard Worker if (!query.Evaluate(*events.at(i)))
1029*635a8641SAndroid Build Coastguard Worker continue;
1030*635a8641SAndroid Build Coastguard Worker if (closest == events.size()) {
1031*635a8641SAndroid Build Coastguard Worker closest = i;
1032*635a8641SAndroid Build Coastguard Worker continue;
1033*635a8641SAndroid Build Coastguard Worker }
1034*635a8641SAndroid Build Coastguard Worker if (fabs(events.at(i)->timestamp - events.at(position)->timestamp) <
1035*635a8641SAndroid Build Coastguard Worker fabs(events.at(closest)->timestamp - events.at(position)->timestamp)) {
1036*635a8641SAndroid Build Coastguard Worker second_closest = closest;
1037*635a8641SAndroid Build Coastguard Worker closest = i;
1038*635a8641SAndroid Build Coastguard Worker } else if (second_closest == events.size()) {
1039*635a8641SAndroid Build Coastguard Worker second_closest = i;
1040*635a8641SAndroid Build Coastguard Worker }
1041*635a8641SAndroid Build Coastguard Worker }
1042*635a8641SAndroid Build Coastguard Worker
1043*635a8641SAndroid Build Coastguard Worker if (closest < events.size() &&
1044*635a8641SAndroid Build Coastguard Worker (!return_second_closest || second_closest < events.size())) {
1045*635a8641SAndroid Build Coastguard Worker *return_closest = closest;
1046*635a8641SAndroid Build Coastguard Worker if (return_second_closest)
1047*635a8641SAndroid Build Coastguard Worker *return_second_closest = second_closest;
1048*635a8641SAndroid Build Coastguard Worker return true;
1049*635a8641SAndroid Build Coastguard Worker }
1050*635a8641SAndroid Build Coastguard Worker
1051*635a8641SAndroid Build Coastguard Worker return false;
1052*635a8641SAndroid Build Coastguard Worker }
1053*635a8641SAndroid Build Coastguard Worker
CountMatches(const TraceEventVector & events,const Query & query,size_t begin_position,size_t end_position)1054*635a8641SAndroid Build Coastguard Worker size_t CountMatches(const TraceEventVector& events,
1055*635a8641SAndroid Build Coastguard Worker const Query& query,
1056*635a8641SAndroid Build Coastguard Worker size_t begin_position,
1057*635a8641SAndroid Build Coastguard Worker size_t end_position) {
1058*635a8641SAndroid Build Coastguard Worker if (begin_position >= events.size())
1059*635a8641SAndroid Build Coastguard Worker return 0u;
1060*635a8641SAndroid Build Coastguard Worker end_position = (end_position < events.size()) ? end_position : events.size();
1061*635a8641SAndroid Build Coastguard Worker size_t count = 0u;
1062*635a8641SAndroid Build Coastguard Worker for (size_t i = begin_position; i < end_position; ++i) {
1063*635a8641SAndroid Build Coastguard Worker if (query.Evaluate(*events.at(i)))
1064*635a8641SAndroid Build Coastguard Worker ++count;
1065*635a8641SAndroid Build Coastguard Worker }
1066*635a8641SAndroid Build Coastguard Worker return count;
1067*635a8641SAndroid Build Coastguard Worker }
1068*635a8641SAndroid Build Coastguard Worker
1069*635a8641SAndroid Build Coastguard Worker } // namespace trace_analyzer
1070