OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <memory> | |
6 #include <set> | |
7 #include <string> | |
8 #include <vector> | |
9 | |
10 #include "apps/benchmark/args.h" | |
11 #include "apps/benchmark/event.h" | |
12 #include "apps/benchmark/measurements.h" | |
13 #include "apps/benchmark/trace_collector_client.h" | |
14 #include "base/bind.h" | |
15 #include "base/json/json_reader.h" | |
16 #include "base/macros.h" | |
17 #include "base/memory/scoped_ptr.h" | |
18 #include "base/strings/string_util.h" | |
19 #include "base/time/time.h" | |
20 #include "base/trace_event/trace_event.h" | |
21 #include "base/values.h" | |
22 #include "mojo/application/application_runner_chromium.h" | |
23 #include "mojo/common/tracing_impl.h" | |
24 #include "mojo/public/c/system/main.h" | |
25 #include "mojo/public/cpp/application/application_connection.h" | |
26 #include "mojo/public/cpp/application/application_delegate.h" | |
27 #include "mojo/public/cpp/application/application_impl.h" | |
28 #include "mojo/services/tracing/public/interfaces/tracing.mojom.h" | |
29 | |
30 namespace benchmark { | |
31 namespace { | |
32 | |
33 const char* kOriginEventCategory = "benchmark"; | |
34 const char* kOriginEventName = "time_origin"; | |
35 | |
36 class BenchmarkApp : public mojo::ApplicationDelegate, | |
37 public TraceCollectorClient::Receiver { | |
38 public: | |
39 BenchmarkApp() {} | |
40 ~BenchmarkApp() override {} | |
41 | |
42 // mojo:ApplicationDelegate: | |
43 void Initialize(mojo::ApplicationImpl* app) override { | |
44 // Parse command-line arguments. | |
45 if (!GetArgs(app->args(), &args_)) { | |
46 mojo::ApplicationImpl::Terminate(); | |
47 return; | |
48 } | |
49 | |
50 // Initialize tracing in the benchmark app itself, so that we can record the | |
51 // time origin trace event. | |
jamesr
2015/08/21 22:56:16
i'm not sure why this is needed - isn't the tracin
ppi
2015/08/24 15:41:05
Done.
| |
52 tracing_.Initialize(app); | |
jamesr
2015/08/21 22:56:16
you would want to do this if you wanted this app t
ppi
2015/08/24 15:41:05
Done.
| |
53 tracing_.set_tracing_already_started(true); | |
54 base::trace_event::TraceLog::GetInstance()->SetEnabled( | |
55 base::trace_event::TraceConfig(kOriginEventCategory, | |
56 base::trace_event::RECORD_UNTIL_FULL), | |
57 base::trace_event::TraceLog::RECORDING_MODE); | |
58 | |
59 // Calculate a list of trace categories we want to collect: a union of all | |
60 // categories targeted in measurements and kOriginEventCategory. | |
61 std::set<std::string> category_set; | |
62 category_set.insert(kOriginEventCategory); | |
63 for (const Measurement& measurement : args_.measurements) { | |
64 category_set.insert(measurement.target_event.category); | |
65 } | |
66 std::vector<std::string> unique_categories(category_set.begin(), | |
67 category_set.end()); | |
68 std::string categories_str = JoinString(unique_categories, ','); | |
69 | |
70 // Connect to trace collector. It will fetch trace events produced both by | |
71 // the app being benchmarked and by the benchmark app. | |
72 tracing::TraceCollectorPtr trace_collector; | |
73 app->ConnectToService("mojo:tracing", &trace_collector); | |
74 trace_collector_client_.reset( | |
75 new TraceCollectorClient(this, trace_collector.Pass())); | |
76 trace_collector_client_->Start(categories_str); | |
77 | |
78 // Record reference event serving as the time origin for measurements. This | |
79 // happens just before connecting to the app being benchmarked. | |
80 TRACE_EVENT_INSTANT0(kOriginEventCategory, kOriginEventName, | |
81 TRACE_EVENT_SCOPE_THREAD); | |
82 traced_app_connection_ = app->ConnectToApplication(args_.app); | |
83 | |
84 // Post task to stop tracing when the time is up. | |
85 base::MessageLoop::current()->PostDelayedTask( | |
86 FROM_HERE, | |
87 base::Bind(&BenchmarkApp::StopTracing, base::Unretained(this)), | |
88 args_.duration); | |
89 } | |
90 | |
91 void StopTracing() { | |
92 // Request the trace collector to send back the data. When the data is ready | |
93 // we will be called at OnTraceCollected(). | |
94 trace_collector_client_->Stop(); | |
95 } | |
96 | |
97 // TraceCollectorClient::Receiver: | |
98 void OnTraceCollected(std::string trace_data) override { | |
99 // Parse the JSON string describing the events. | |
100 base::JSONReader reader; | |
101 scoped_ptr<base::Value> parsed_trace_data = reader.ReadToValue(trace_data); | |
102 if (!parsed_trace_data) { | |
103 LOG(ERROR) << "Failed to parse trace data (bad format): " | |
104 << reader.GetErrorMessage(); | |
105 mojo::ApplicationImpl::Terminate(); | |
106 return; | |
107 } | |
108 | |
109 // Parse the events from the JSON tree. | |
110 std::vector<Event> events; | |
111 if (!GetEvents(parsed_trace_data.Pass(), &events)) { | |
112 LOG(ERROR) << "Failed to parse the trace data (bad content)"; | |
113 mojo::ApplicationImpl::Terminate(); | |
114 return; | |
115 } | |
116 | |
117 // Calculate and print the results. | |
118 EventSpec time_origin_spec = | |
119 EventSpec({.name = kOriginEventName, .category = kOriginEventCategory}); | |
120 Measurements measurements(events, time_origin_spec); | |
121 for (const Measurement& measurement : args_.measurements) { | |
122 double result = measurements.Measure(measurement); | |
123 printf("measurement: %s %lf\n", measurement.spec.c_str(), result); | |
124 } | |
125 | |
126 // Scripts that run benchmarks can pick this up as a signal that the run | |
127 // succeeded (as shell exit code is still 0 if we exit early due to an | |
128 // error). | |
129 printf("benchmark succeeded\n"); | |
130 mojo::ApplicationImpl::Terminate(); | |
131 } | |
132 | |
133 private: | |
134 Args args_; | |
135 mojo::ApplicationConnection* traced_app_connection_; | |
136 scoped_ptr<TraceCollectorClient> trace_collector_client_; | |
137 mojo::TracingImpl tracing_; | |
138 EventSpec time_origin_; | |
139 | |
140 DISALLOW_COPY_AND_ASSIGN(BenchmarkApp); | |
141 }; | |
142 } // namespace | |
143 } // namespace benchmark | |
144 | |
145 MojoResult MojoMain(MojoHandle application_request) { | |
146 mojo::ApplicationRunnerChromium runner(new benchmark::BenchmarkApp); | |
147 auto ret = runner.Run(application_request); | |
148 fflush(NULL); | |
jamesr
2015/08/21 22:56:16
use 'nullptr', this is c++ code
ppi
2015/08/24 15:41:05
Done.
| |
149 return ret; | |
150 } | |
OLD | NEW |