blob: d05596e7f634f2359863f965e20323109ed0fc2f [file] [log] [blame]
Ioannis Ilkoseff38f52018-10-29 10:37:55 +00001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "src/trace_processor/trace_processor_impl.h"
18
Ioannis Ilkosb8b11102019-01-29 17:56:55 +000019#include <inttypes.h>
Hector Dearmanc0a29092018-11-08 17:34:23 +000020#include <algorithm>
Ioannis Ilkoseff38f52018-10-29 10:37:55 +000021
Lalit Maganti77095012019-02-19 13:13:59 +000022#include "perfetto/base/logging.h"
Eric Seckler83dcc8c2019-08-21 12:18:43 +010023#include "perfetto/base/time.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010024#include "perfetto/ext/base/string_splitter.h"
25#include "perfetto/ext/base/string_utils.h"
Lalit Maganti1f4712b2020-04-14 21:01:13 +010026#include "src/trace_processor/dynamic/describe_slice_generator.h"
27#include "src/trace_processor/dynamic/experimental_counter_dur_generator.h"
28#include "src/trace_processor/dynamic/experimental_flamegraph_generator.h"
Lalit Maganti0bfeb972020-03-14 03:57:30 +000029#include "src/trace_processor/export_json.h"
Lalit Maganti60af4ef2020-04-15 14:27:09 +010030#include "src/trace_processor/importers/additional_modules.h"
Mikhail Khokhlov81491b92019-12-19 13:58:22 +000031#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
Lalit Maganti6d1f7b52020-02-27 13:16:44 +000032#include "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h"
33#include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
Lalit Maganti9d538bd2020-03-12 23:48:16 +000034#include "src/trace_processor/importers/gzip/gzip_trace_parser.h"
Lalit Maganti6d1f7b52020-02-27 13:16:44 +000035#include "src/trace_processor/importers/json/json_trace_parser.h"
36#include "src/trace_processor/importers/json/json_trace_tokenizer.h"
Lalit Maganti05819e22020-04-14 21:01:38 +010037#include "src/trace_processor/importers/proto/metadata_tracker.h"
Lalit Maganti6d1f7b52020-02-27 13:16:44 +000038#include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
Lalit Maganti60732452020-02-04 16:02:53 +000039#include "src/trace_processor/sqlite/span_join_operator_table.h"
Lalit Maganti655adae2020-04-14 21:01:25 +010040#include "src/trace_processor/sqlite/sql_stats_table.h"
Lalit Maganti03d10622019-08-27 14:47:39 +010041#include "src/trace_processor/sqlite/sqlite3_str_split.h"
Lalit Maganti655adae2020-04-14 21:01:25 +010042#include "src/trace_processor/sqlite/sqlite_raw_table.h"
Lalit Maganti737b3762019-08-26 13:46:37 -070043#include "src/trace_processor/sqlite/sqlite_table.h"
Lalit Maganti1b620a62020-01-30 18:24:53 +000044#include "src/trace_processor/sqlite/sqlite_utils.h"
Lalit Maganti655adae2020-04-14 21:01:25 +010045#include "src/trace_processor/sqlite/stats_table.h"
Lalit Maganti60732452020-02-04 16:02:53 +000046#include "src/trace_processor/sqlite/window_operator_table.h"
Lalit Maganti83b53fa2020-01-13 12:55:36 +000047#include "src/trace_processor/types/variadic.h"
Ioannis Ilkoseff38f52018-10-29 10:37:55 +000048
Eric Secklerc622b8b2019-10-21 09:54:00 +010049#include "src/trace_processor/metrics/metrics.descriptor.h"
50#include "src/trace_processor/metrics/metrics.h"
51#include "src/trace_processor/metrics/sql_metrics.h"
Lalit Maganti26f69bd2019-04-29 18:23:47 +010052
Primiano Tuccia1a26de2019-11-12 15:45:19 -080053#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
54#include <cxxabi.h>
55#endif
56
Mikhail Khokhlov8643d1c2019-06-04 12:02:47 +010057// In Android and Chromium tree builds, we don't have the percentile module.
Lalit Maganti17aa2732019-02-08 15:47:26 +000058// Just don't include it.
Primiano Tucci02c11762019-08-30 00:57:59 +020059#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000060// defined in sqlite_src/ext/misc/percentile.c
61extern "C" int sqlite3_percentile_init(sqlite3* db,
62 char** error,
63 const sqlite3_api_routines* api);
Eric Secklera7870e62019-11-01 10:11:58 +000064#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000065
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000066namespace perfetto {
67namespace trace_processor {
Ioannis Ilkos178535e2018-11-05 17:32:45 +000068namespace {
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000069
Primiano Tucci11a79e72019-10-29 22:13:10 +010070const char kAllTablesQuery[] =
71 "SELECT tbl_name, type FROM (SELECT * FROM sqlite_master UNION ALL SELECT "
72 "* FROM sqlite_temp_master)";
73
Ioannis Ilkos7199d552019-03-13 18:35:31 +000074void InitializeSqlite(sqlite3* db) {
75 char* error = nullptr;
76 sqlite3_exec(db, "PRAGMA temp_store=2", 0, 0, &error);
77 if (error) {
78 PERFETTO_FATAL("Error setting pragma temp_store: %s", error);
79 }
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000080 sqlite3_str_split_init(db);
Lalit Maganti17aa2732019-02-08 15:47:26 +000081// In Android tree builds, we don't have the percentile module.
82// Just don't include it.
Primiano Tucci02c11762019-08-30 00:57:59 +020083#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000084 sqlite3_percentile_init(db, &error, nullptr);
Sami Kyostila33668942018-11-13 16:33:32 +000085 if (error) {
Ioannis Ilkos178535e2018-11-05 17:32:45 +000086 PERFETTO_ELOG("Error initializing: %s", error);
Sami Kyostila33668942018-11-13 16:33:32 +000087 sqlite3_free(error);
88 }
Lalit Maganti17aa2732019-02-08 15:47:26 +000089#endif
Sami Kyostila33668942018-11-13 16:33:32 +000090}
91
Lalit Maganti086295b2019-04-04 16:59:19 +010092void BuildBoundsTable(sqlite3* db, std::pair<int64_t, int64_t> bounds) {
93 char* error = nullptr;
94 sqlite3_exec(db, "DELETE FROM trace_bounds", nullptr, nullptr, &error);
95 if (error) {
96 PERFETTO_ELOG("Error deleting from bounds table: %s", error);
97 sqlite3_free(error);
98 return;
99 }
100
101 char* insert_sql = sqlite3_mprintf("INSERT INTO trace_bounds VALUES(%" PRId64
102 ", %" PRId64 ")",
103 bounds.first, bounds.second);
104
105 sqlite3_exec(db, insert_sql, 0, 0, &error);
106 sqlite3_free(insert_sql);
107 if (error) {
108 PERFETTO_ELOG("Error inserting bounds table: %s", error);
109 sqlite3_free(error);
110 }
111}
112
Sami Kyostila33668942018-11-13 16:33:32 +0000113void CreateBuiltinTables(sqlite3* db) {
114 char* error = nullptr;
115 sqlite3_exec(db, "CREATE TABLE perfetto_tables(name STRING)", 0, 0, &error);
116 if (error) {
117 PERFETTO_ELOG("Error initializing: %s", error);
118 sqlite3_free(error);
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000119 }
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000120 sqlite3_exec(db,
121 "CREATE TABLE trace_bounds(start_ts BIG INT, end_ts BIG INT)", 0,
122 0, &error);
123 if (error) {
124 PERFETTO_ELOG("Error initializing: %s", error);
125 sqlite3_free(error);
126 }
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000127
Lalit Maganti086295b2019-04-04 16:59:19 +0100128 // Initialize the bounds table with some data so even before parsing any data,
129 // we still have a valid table.
130 BuildBoundsTable(db, std::make_pair(0, 0));
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000131}
Hector Dearmanc0a29092018-11-08 17:34:23 +0000132
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000133void CreateBuiltinViews(sqlite3* db) {
134 char* error = nullptr;
135 sqlite3_exec(db,
Lalit Maganti809b2f92019-11-07 13:27:26 +0000136 "CREATE VIEW counter_definitions AS "
137 "SELECT "
138 " *, "
Lalit Magantibbc97002019-11-07 17:57:23 +0000139 " id AS counter_id "
Lalit Maganti809b2f92019-11-07 13:27:26 +0000140 "FROM counter_track",
141 0, 0, &error);
142 if (error) {
143 PERFETTO_ELOG("Error initializing: %s", error);
144 sqlite3_free(error);
145 }
146
147 sqlite3_exec(db,
Lalit Maganti69c94442019-11-07 18:59:02 +0000148 "CREATE VIEW counter_values AS "
149 "SELECT "
150 " *, "
151 " track_id as counter_id "
152 "FROM counter",
Lalit Magantibbc97002019-11-07 17:57:23 +0000153 0, 0, &error);
154 if (error) {
155 PERFETTO_ELOG("Error initializing: %s", error);
156 sqlite3_free(error);
157 }
158
159 sqlite3_exec(db,
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000160 "CREATE VIEW counters AS "
Lalit Maganti69c94442019-11-07 18:59:02 +0000161 "SELECT * "
Lalit Magantibbc97002019-11-07 17:57:23 +0000162 "FROM counter_values v "
163 "INNER JOIN counter_track t "
164 "ON v.track_id = t.id "
Lalit Maganti6fbb0ad2019-10-25 14:42:28 +0100165 "ORDER BY ts;",
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000166 0, 0, &error);
167 if (error) {
168 PERFETTO_ELOG("Error initializing: %s", error);
169 sqlite3_free(error);
170 }
Eric Seckler972225e2019-04-18 11:07:12 +0100171
172 sqlite3_exec(db,
173 "CREATE VIEW slice AS "
174 "SELECT "
175 " *, "
Lalit Magantibbc97002019-11-07 17:57:23 +0000176 " category AS cat, "
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000177 " id AS slice_id "
Eric Seckler972225e2019-04-18 11:07:12 +0100178 "FROM internal_slice;",
179 0, 0, &error);
180 if (error) {
181 PERFETTO_ELOG("Error initializing: %s", error);
182 sqlite3_free(error);
183 }
184
Lalit Maganti24b08332019-10-04 12:53:08 +0100185 sqlite3_exec(db,
Lalit Maganti80f566d2020-01-06 13:35:01 +0000186 "CREATE VIEW instants AS "
187 "SELECT "
188 "*, "
189 "0.0 as value "
190 "FROM instant;",
191 0, 0, &error);
Lalit Maganti1b620a62020-01-30 18:24:53 +0000192
193 if (error) {
194 PERFETTO_ELOG("Error initializing: %s", error);
195 sqlite3_free(error);
196 }
197
198 sqlite3_exec(db,
199 "CREATE VIEW sched AS "
200 "SELECT "
201 "*, "
202 "ts + dur as ts_end "
203 "FROM sched_slice;",
204 0, 0, &error);
205
Lalit Maganti80f566d2020-01-06 13:35:01 +0000206 if (error) {
207 PERFETTO_ELOG("Error initializing: %s", error);
208 sqlite3_free(error);
209 }
210
Eric Seckler972225e2019-04-18 11:07:12 +0100211 // Legacy view for "slice" table with a deprecated table name.
212 // TODO(eseckler): Remove this view when all users have switched to "slice".
213 sqlite3_exec(db,
214 "CREATE VIEW slices AS "
215 "SELECT * FROM slice;",
216 0, 0, &error);
217 if (error) {
218 PERFETTO_ELOG("Error initializing: %s", error);
219 sqlite3_free(error);
220 }
Lalit Magantieac7fff2020-01-10 16:42:54 +0000221
222 sqlite3_exec(db,
223 "CREATE VIEW thread AS "
224 "SELECT "
225 "id as utid, "
226 "* "
227 "FROM internal_thread;",
228 0, 0, &error);
229 if (error) {
230 PERFETTO_ELOG("Error initializing: %s", error);
231 sqlite3_free(error);
232 }
233
234 sqlite3_exec(db,
235 "CREATE VIEW process AS "
236 "SELECT "
237 "id as upid, "
238 "* "
239 "FROM internal_process;",
240 0, 0, &error);
241 if (error) {
242 PERFETTO_ELOG("Error initializing: %s", error);
243 sqlite3_free(error);
244 }
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000245}
246
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100247void ExportJson(sqlite3_context* ctx, int /*argc*/, sqlite3_value** argv) {
248 TraceStorage* storage = static_cast<TraceStorage*>(sqlite3_user_data(ctx));
Eric Seckler37ad6af2019-10-08 15:51:14 +0100249 FILE* output;
250 if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
251 // Assume input is an FD.
252 output = fdopen(sqlite3_value_int(argv[0]), "w");
253 if (!output) {
254 sqlite3_result_error(ctx, "Couldn't open output file from given FD", -1);
255 return;
256 }
257 } else {
258 const char* filename =
259 reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
260 output = fopen(filename, "w");
261 if (!output) {
262 sqlite3_result_error(ctx, "Couldn't open output file", -1);
263 return;
264 }
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100265 }
266
Eric Seckler7fb1d232019-10-23 14:42:43 +0100267 util::Status result = json::ExportJson(storage, output);
268 if (!result.ok()) {
269 sqlite3_result_error(ctx, result.message().c_str(), -1);
270 return;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100271 }
272}
273
274void CreateJsonExportFunction(TraceStorage* ts, sqlite3* db) {
275 auto ret = sqlite3_create_function_v2(db, "EXPORT_JSON", 1, SQLITE_UTF8, ts,
276 ExportJson, nullptr, nullptr,
277 sqlite_utils::kSqliteStatic);
278 if (ret) {
279 PERFETTO_ELOG("Error initializing EXPORT_JSON");
280 }
281}
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100282
Lalit Maganti062c8f82019-10-03 20:11:29 +0100283void Hash(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
284 base::Hash hash;
285 for (int i = 0; i < argc; ++i) {
286 sqlite3_value* value = argv[i];
287 switch (sqlite3_value_type(value)) {
288 case SQLITE_INTEGER:
289 hash.Update(sqlite3_value_int64(value));
290 break;
291 case SQLITE_TEXT: {
292 const char* ptr =
293 reinterpret_cast<const char*>(sqlite3_value_text(value));
294 hash.Update(ptr, strlen(ptr));
295 break;
296 }
297 default:
298 sqlite3_result_error(ctx, "Unsupported type of arg passed to HASH", -1);
299 return;
300 }
301 }
302 sqlite3_result_int64(ctx, static_cast<int64_t>(hash.digest()));
303}
304
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000305void Demangle(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
306 if (argc != 1) {
307 sqlite3_result_error(ctx, "Unsupported number of arg passed to DEMANGLE",
308 -1);
309 return;
310 }
311 sqlite3_value* value = argv[0];
312 if (sqlite3_value_type(value) != SQLITE_TEXT) {
313 sqlite3_result_error(ctx, "Unsupported type of arg passed to DEMANGLE", -1);
314 return;
315 }
316 const char* ptr = reinterpret_cast<const char*>(sqlite3_value_text(value));
Primiano Tuccia1a26de2019-11-12 15:45:19 -0800317#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000318 int ignored = 0;
319 // This memory was allocated by malloc and will be passed to SQLite to free.
320 char* demangled_name = abi::__cxa_demangle(ptr, nullptr, nullptr, &ignored);
321 if (!demangled_name) {
322 sqlite3_result_null(ctx);
323 return;
324 }
325 sqlite3_result_text(ctx, demangled_name, -1, free);
Primiano Tuccia1a26de2019-11-12 15:45:19 -0800326#else
327 sqlite3_result_text(ctx, ptr, -1, sqlite_utils::kSqliteTransient);
328#endif
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000329}
330
Pascal Muetschard7e476092020-01-15 16:41:30 -0800331void LastNonNullStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
332 if (argc != 1) {
Lalit Maganti9bd8cd32020-03-24 16:00:05 +0000333 sqlite3_result_error(
334 ctx, "Unsupported number of args passed to LAST_NON_NULL", -1);
Pascal Muetschard7e476092020-01-15 16:41:30 -0800335 return;
336 }
337 sqlite3_value* value = argv[0];
338 if (sqlite3_value_type(value) == SQLITE_NULL) {
339 return;
340 }
341 sqlite3_value** ptr = reinterpret_cast<sqlite3_value**>(
342 sqlite3_aggregate_context(ctx, sizeof(sqlite3_value*)));
343 if (ptr) {
344 if (*ptr != nullptr) {
345 sqlite3_value_free(*ptr);
346 }
347 *ptr = sqlite3_value_dup(value);
348 }
349}
350
351void LastNonNullInverse(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
352 // Do nothing.
353 base::ignore_result(ctx);
354 base::ignore_result(argc);
355 base::ignore_result(argv);
356}
357
358void LastNonNullValue(sqlite3_context* ctx) {
359 sqlite3_value** ptr =
360 reinterpret_cast<sqlite3_value**>(sqlite3_aggregate_context(ctx, 0));
361 if (!ptr || !*ptr) {
362 sqlite3_result_null(ctx);
363 } else {
364 sqlite3_result_value(ctx, *ptr);
365 }
366}
367
368void LastNonNullFinal(sqlite3_context* ctx) {
369 sqlite3_value** ptr =
370 reinterpret_cast<sqlite3_value**>(sqlite3_aggregate_context(ctx, 0));
371 if (!ptr || !*ptr) {
372 sqlite3_result_null(ctx);
373 } else {
374 sqlite3_result_value(ctx, *ptr);
375 sqlite3_value_free(*ptr);
376 }
377}
378
Lalit Maganti062c8f82019-10-03 20:11:29 +0100379void CreateHashFunction(sqlite3* db) {
380 auto ret = sqlite3_create_function_v2(
381 db, "HASH", -1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &Hash,
382 nullptr, nullptr, nullptr);
383 if (ret) {
384 PERFETTO_ELOG("Error initializing HASH");
385 }
386}
387
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000388void CreateDemangledNameFunction(sqlite3* db) {
389 auto ret = sqlite3_create_function_v2(
390 db, "DEMANGLE", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &Demangle,
391 nullptr, nullptr, nullptr);
392 if (ret != SQLITE_OK) {
393 PERFETTO_ELOG("Error initializing DEMANGLE: %s", sqlite3_errmsg(db));
394 }
395}
396
Pascal Muetschard7e476092020-01-15 16:41:30 -0800397void CreateLastNonNullFunction(sqlite3* db) {
398 auto ret = sqlite3_create_window_function(
399 db, "LAST_NON_NULL", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr,
400 &LastNonNullStep, &LastNonNullFinal, &LastNonNullValue,
401 &LastNonNullInverse, nullptr);
402 if (ret) {
403 PERFETTO_ELOG("Error initializing LAST_NON_NULL");
404 }
405}
406
Lalit Maganti2553b802019-05-24 13:25:58 +0100407void SetupMetrics(TraceProcessor* tp,
408 sqlite3* db,
Lalit Maganti2553b802019-05-24 13:25:58 +0100409 std::vector<metrics::SqlMetricFile>* sql_metrics) {
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100410 tp->ExtendMetricsProto(kMetricsDescriptor.data(), kMetricsDescriptor.size());
411
Lalit Maganti2553b802019-05-24 13:25:58 +0100412 for (const auto& file_to_sql : metrics::sql_metrics::kFileToSql) {
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100413 tp->RegisterMetric(file_to_sql.path, file_to_sql.sql);
Lalit Maganti2553b802019-05-24 13:25:58 +0100414 }
415
416 {
417 std::unique_ptr<metrics::RunMetricContext> ctx(
418 new metrics::RunMetricContext());
419 ctx->tp = tp;
420 ctx->metrics = sql_metrics;
421 auto ret = sqlite3_create_function_v2(
422 db, "RUN_METRIC", -1, SQLITE_UTF8, ctx.release(), metrics::RunMetric,
423 nullptr, nullptr,
424 [](void* ptr) { delete static_cast<metrics::RunMetricContext*>(ptr); });
425 if (ret)
426 PERFETTO_ELOG("Error initializing RUN_METRIC");
427 }
428
429 {
430 auto ret = sqlite3_create_function_v2(
431 db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr,
432 metrics::RepeatedFieldStep, metrics::RepeatedFieldFinal, nullptr);
433 if (ret)
434 PERFETTO_ELOG("Error initializing RepeatedField");
435 }
436}
Oystein Eftevaag477bbff2020-01-27 11:07:49 -0800437
438void EnsureSqliteInitialized() {
439 // sqlite3_initialize isn't actually thread-safe despite being documented
440 // as such; we need to make sure multiple TraceProcessorImpl instances don't
441 // call it concurrently and only gets called once per process, instead.
Lalit Maganti1e5630e2020-01-29 12:34:14 +0000442 static bool init_once = [] { return sqlite3_initialize() == SQLITE_OK; }();
Oystein Eftevaag477bbff2020-01-27 11:07:49 -0800443 PERFETTO_CHECK(init_once);
444}
445
Hector Dearmanc0a29092018-11-08 17:34:23 +0000446} // namespace
447
Eric Secklera7870e62019-11-01 10:11:58 +0000448TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
449 : TraceProcessorStorageImpl(cfg) {
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000450 context_.fuchsia_trace_tokenizer.reset(new FuchsiaTraceTokenizer(&context_));
451 context_.fuchsia_trace_parser.reset(new FuchsiaTraceParser(&context_));
452
453 context_.systrace_trace_parser.reset(new SystraceTraceParser(&context_));
454
Lalit Maganti0bfeb972020-03-14 03:57:30 +0000455 if (gzip::IsGzipSupported())
Lalit Maganti9d538bd2020-03-12 23:48:16 +0000456 context_.gzip_trace_parser.reset(new GzipTraceParser(&context_));
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000457
Lalit Maganti0bfeb972020-03-14 03:57:30 +0000458 if (json::IsJsonSupported()) {
459 context_.json_trace_tokenizer.reset(new JsonTraceTokenizer(&context_));
460 context_.json_trace_parser.reset(new JsonTraceParser(&context_));
461 }
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000462
Mikhail Khokhlov692087e2019-12-11 10:53:45 +0000463 RegisterAdditionalModules(&context_);
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000464
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000465 sqlite3* db = nullptr;
Oystein Eftevaag477bbff2020-01-27 11:07:49 -0800466 EnsureSqliteInitialized();
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000467 PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
Ioannis Ilkos7199d552019-03-13 18:35:31 +0000468 InitializeSqlite(db);
Sami Kyostila33668942018-11-13 16:33:32 +0000469 CreateBuiltinTables(db);
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000470 CreateBuiltinViews(db);
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000471 db_.reset(std::move(db));
472
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100473 CreateJsonExportFunction(this->context_.storage.get(), db);
Lalit Maganti062c8f82019-10-03 20:11:29 +0100474 CreateHashFunction(db);
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000475 CreateDemangledNameFunction(db);
Pascal Muetschard7e476092020-01-15 16:41:30 -0800476 CreateLastNonNullFunction(db);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100477
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100478 SetupMetrics(this, *db_, &sql_metrics_);
Lalit Maganti2553b802019-05-24 13:25:58 +0100479
Lalit Maganti65800eb2020-01-30 15:18:59 +0000480 // Setup the query cache.
481 query_cache_.reset(new QueryCache());
482
Lalit Maganti786cc922019-09-06 16:04:32 +0100483 const TraceStorage* storage = context_.storage.get();
Lalit Maganti809b2f92019-11-07 13:27:26 +0000484
Lalit Maganti679b29d2020-01-13 13:26:28 +0000485 SqlStatsTable::RegisterTable(*db_, storage);
Lalit Maganti679b29d2020-01-13 13:26:28 +0000486 StatsTable::RegisterTable(*db_, storage);
487
Lalit Maganti8a39fae2020-01-20 17:22:10 +0000488 // Operator tables.
489 SpanJoinOperatorTable::RegisterTable(*db_, storage);
490 WindowOperatorTable::RegisterTable(*db_, storage);
491
Lalit Maganti679b29d2020-01-13 13:26:28 +0000492 // New style tables but with some custom logic.
Lalit Maganti65800eb2020-01-30 15:18:59 +0000493 SqliteRawTable::RegisterTable(*db_, query_cache_.get(),
494 context_.storage.get());
Lalit Maganti920f4f92020-02-19 13:45:05 +0000495
496 // Tables dynamically generated at query time.
497 RegisterDynamicTable(std::unique_ptr<ExperimentalFlamegraphGenerator>(
498 new ExperimentalFlamegraphGenerator(&context_)));
499 RegisterDynamicTable(std::unique_ptr<ExperimentalCounterDurGenerator>(
500 new ExperimentalCounterDurGenerator(storage->counter_table())));
Lalit Maganti97d7d472020-04-07 18:49:17 +0100501 RegisterDynamicTable(std::unique_ptr<DescribeSliceGenerator>(
502 new DescribeSliceGenerator(&context_)));
Lalit Maganti679b29d2020-01-13 13:26:28 +0000503
504 // New style db-backed tables.
Lalit Maganti65800eb2020-01-30 15:18:59 +0000505 RegisterDbTable(storage->arg_table());
506 RegisterDbTable(storage->thread_table());
507 RegisterDbTable(storage->process_table());
Lalit Maganti1908e262020-01-09 14:33:19 +0000508
Lalit Maganti65800eb2020-01-30 15:18:59 +0000509 RegisterDbTable(storage->slice_table());
Lalit Maganti1b620a62020-01-30 18:24:53 +0000510 RegisterDbTable(storage->sched_slice_table());
Lalit Maganti65800eb2020-01-30 15:18:59 +0000511 RegisterDbTable(storage->instant_table());
512 RegisterDbTable(storage->gpu_slice_table());
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000513
Lalit Maganti65800eb2020-01-30 15:18:59 +0000514 RegisterDbTable(storage->track_table());
515 RegisterDbTable(storage->thread_track_table());
516 RegisterDbTable(storage->process_track_table());
517 RegisterDbTable(storage->gpu_track_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000518
Lalit Maganti65800eb2020-01-30 15:18:59 +0000519 RegisterDbTable(storage->counter_table());
Lalit Maganti4b3b3ad2019-12-04 19:27:35 +0000520
Lalit Maganti65800eb2020-01-30 15:18:59 +0000521 RegisterDbTable(storage->counter_track_table());
522 RegisterDbTable(storage->process_counter_track_table());
523 RegisterDbTable(storage->thread_counter_track_table());
524 RegisterDbTable(storage->cpu_counter_track_table());
525 RegisterDbTable(storage->irq_counter_track_table());
526 RegisterDbTable(storage->softirq_counter_track_table());
527 RegisterDbTable(storage->gpu_counter_track_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000528
Lalit Maganti65800eb2020-01-30 15:18:59 +0000529 RegisterDbTable(storage->heap_graph_object_table());
530 RegisterDbTable(storage->heap_graph_reference_table());
Florian Mayer22588ad2020-04-08 16:14:34 +0200531 RegisterDbTable(storage->heap_graph_class_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000532
Lalit Maganti65800eb2020-01-30 15:18:59 +0000533 RegisterDbTable(storage->symbol_table());
534 RegisterDbTable(storage->heap_profile_allocation_table());
535 RegisterDbTable(storage->cpu_profile_stack_sample_table());
536 RegisterDbTable(storage->stack_profile_callsite_table());
537 RegisterDbTable(storage->stack_profile_mapping_table());
538 RegisterDbTable(storage->stack_profile_frame_table());
Florian Mayer19ce3952020-04-08 15:27:32 +0200539 RegisterDbTable(storage->package_list_table());
Florian Mayer2f12d432020-04-09 14:42:46 +0200540 RegisterDbTable(storage->profiler_smaps_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000541
Lalit Maganti65800eb2020-01-30 15:18:59 +0000542 RegisterDbTable(storage->android_log_table());
Lalit Magantif1ab24f2020-01-07 17:42:26 +0000543
Lalit Maganti65800eb2020-01-30 15:18:59 +0000544 RegisterDbTable(storage->vulkan_memory_allocations_table());
Lalit Magantiededb0e2020-01-08 12:50:34 +0000545
Adithya Srinivasan4d9bf422020-03-24 13:33:16 -0700546 RegisterDbTable(storage->graphics_frame_slice_table());
547 RegisterDbTable(storage->graphics_frame_stats_table());
548
Lalit Maganti65800eb2020-01-30 15:18:59 +0000549 RegisterDbTable(storage->metadata_table());
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000550}
551
Lalit Maganti77095012019-02-19 13:13:59 +0000552TraceProcessorImpl::~TraceProcessorImpl() {
553 for (auto* it : iterators_)
554 it->Reset();
555}
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000556
Lalit Maganti1f067182019-05-09 14:50:05 +0100557util::Status TraceProcessorImpl::Parse(std::unique_ptr<uint8_t[]> data,
558 size_t size) {
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100559 bytes_parsed_ += size;
Eric Secklera7870e62019-11-01 10:11:58 +0000560 return TraceProcessorStorageImpl::Parse(std::move(data), size);
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000561}
562
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100563std::string TraceProcessorImpl::GetCurrentTraceName() {
564 if (current_trace_name_.empty())
565 return "";
566 auto size = " (" + std::to_string(bytes_parsed_ / 1024 / 1024) + " MB)";
567 return current_trace_name_ + size;
568}
569
570void TraceProcessorImpl::SetCurrentTraceName(const std::string& name) {
571 current_trace_name_ = name;
572}
573
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000574void TraceProcessorImpl::NotifyEndOfFile() {
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100575 if (current_trace_name_.empty())
576 current_trace_name_ = "Unnamed trace";
577
Eric Secklera7870e62019-11-01 10:11:58 +0000578 TraceProcessorStorageImpl::NotifyEndOfFile();
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700579
Mikhail Khokhlov81491b92019-12-19 13:58:22 +0000580 SchedEventTracker::GetOrCreate(&context_)->FlushPendingEvents();
Hector Dearman93b0b092020-01-09 14:35:04 +0000581 context_.metadata_tracker->SetMetadata(
582 metadata::trace_size_bytes,
583 Variadic::Integer(static_cast<int64_t>(bytes_parsed_)));
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000584 BuildBoundsTable(*db_, context_.storage->GetTraceTimestampBoundsNs());
Primiano Tucci11a79e72019-10-29 22:13:10 +0100585
586 // Create a snapshot of all tables and views created so far. This is so later
587 // we can drop all extra tables created by the UI and reset to the original
588 // state (see RestoreInitialTables).
589 initial_tables_.clear();
590 auto it = ExecuteQuery(kAllTablesQuery);
591 while (it.Next()) {
592 auto value = it.Get(0);
593 PERFETTO_CHECK(value.type == SqlValue::Type::kString);
594 initial_tables_.push_back(value.string_value);
595 }
596}
597
598size_t TraceProcessorImpl::RestoreInitialTables() {
599 std::vector<std::pair<std::string, std::string>> deletion_list;
600 std::string msg = "Resetting DB to initial state, deleting table/views:";
601 for (auto it = ExecuteQuery(kAllTablesQuery); it.Next();) {
602 std::string name(it.Get(0).string_value);
603 std::string type(it.Get(1).string_value);
604 if (std::find(initial_tables_.begin(), initial_tables_.end(), name) ==
605 initial_tables_.end()) {
606 msg += " " + name;
607 deletion_list.push_back(std::make_pair(type, name));
608 }
609 }
610
611 PERFETTO_LOG("%s", msg.c_str());
612 for (const auto& tn : deletion_list) {
613 std::string query = "DROP " + tn.first + " " + tn.second;
614 auto it = ExecuteQuery(query);
615 while (it.Next()) {
616 }
Primiano Tucci1b4c8fc2020-01-15 22:29:42 +0000617 // Index deletion can legitimately fail. If one creates an index "i" on a
618 // table "t" but issues the deletion in the order (t, i), the DROP index i
619 // will fail with "no such index" because deleting the table "t"
620 // automatically deletes all associated indexes.
621 if (!it.Status().ok() && tn.first != "index")
622 PERFETTO_FATAL("%s -> %s", query.c_str(), it.Status().c_message());
Primiano Tucci11a79e72019-10-29 22:13:10 +0100623 }
624 return deletion_list.size();
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000625}
626
Lalit Maganti77095012019-02-19 13:13:59 +0000627TraceProcessor::Iterator TraceProcessorImpl::ExecuteQuery(
Lalit Magantiaac2f652019-04-30 12:16:21 +0100628 const std::string& sql,
629 int64_t time_queued) {
Lalit Maganti77095012019-02-19 13:13:59 +0000630 sqlite3_stmt* raw_stmt;
Lalit Maganti73b1a0a2019-04-08 13:51:14 +0100631 int err = sqlite3_prepare_v2(*db_, sql.c_str(), static_cast<int>(sql.size()),
Lalit Maganti77095012019-02-19 13:13:59 +0000632 &raw_stmt, nullptr);
Lalit Maganti1f067182019-05-09 14:50:05 +0100633 util::Status status;
Lalit Maganti06acc022019-04-03 16:02:15 +0100634 uint32_t col_count = 0;
635 if (err != SQLITE_OK) {
Lalit Maganti7ee6abb2019-05-09 17:57:32 +0100636 status = util::ErrStatus("%s", sqlite3_errmsg(*db_));
Lalit Maganti77095012019-02-19 13:13:59 +0000637 } else {
638 col_count = static_cast<uint32_t>(sqlite3_column_count(raw_stmt));
639 }
Lalit Magantiaac2f652019-04-30 12:16:21 +0100640
641 base::TimeNanos t_start = base::GetWallTimeNs();
642 uint32_t sql_stats_row =
643 context_.storage->mutable_sql_stats()->RecordQueryBegin(sql, time_queued,
644 t_start.count());
645
646 std::unique_ptr<IteratorImpl> impl(new IteratorImpl(
Lalit Maganti1f067182019-05-09 14:50:05 +0100647 this, *db_, ScopedStmt(raw_stmt), col_count, status, sql_stats_row));
Lalit Maganti77095012019-02-19 13:13:59 +0000648 iterators_.emplace_back(impl.get());
649 return TraceProcessor::Iterator(std::move(impl));
650}
651
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000652void TraceProcessorImpl::InterruptQuery() {
653 if (!db_)
654 return;
655 query_interrupted_.store(true);
656 sqlite3_interrupt(db_.get());
657}
658
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100659util::Status TraceProcessorImpl::RegisterMetric(const std::string& path,
660 const std::string& sql) {
Lalit Magantif9d80302019-06-19 12:48:25 +0100661 std::string stripped_sql;
662 for (base::StringSplitter sp(sql, '\n'); sp.Next();) {
663 if (strncmp(sp.cur_token(), "--", 2) != 0) {
664 stripped_sql.append(sp.cur_token());
665 stripped_sql.push_back('\n');
666 }
667 }
668
669 // Check if the metric with the given path already exists and if it does, just
670 // update the SQL associated with it.
671 auto it = std::find_if(
672 sql_metrics_.begin(), sql_metrics_.end(),
673 [&path](const metrics::SqlMetricFile& m) { return m.path == path; });
674 if (it != sql_metrics_.end()) {
675 it->sql = stripped_sql;
676 return util::OkStatus();
677 }
678
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100679 auto sep_idx = path.rfind("/");
680 std::string basename =
681 sep_idx == std::string::npos ? path : path.substr(sep_idx + 1);
682
683 auto sql_idx = basename.rfind(".sql");
684 if (sql_idx == std::string::npos) {
685 return util::ErrStatus("Unable to find .sql extension for metric");
686 }
687 auto no_ext_name = basename.substr(0, sql_idx);
688
689 metrics::SqlMetricFile metric;
690 metric.path = path;
691 metric.proto_field_name = no_ext_name;
692 metric.output_table_name = no_ext_name + "_output";
Lalit Magantica4d5142019-05-28 13:25:47 +0100693 metric.sql = stripped_sql;
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100694 sql_metrics_.emplace_back(metric);
695 return util::OkStatus();
696}
697
698util::Status TraceProcessorImpl::ExtendMetricsProto(const uint8_t* data,
699 size_t size) {
Lalit Maganti996f5442019-06-21 16:12:58 +0100700 util::Status status = pool_.AddFromFileDescriptorSet(data, size);
701 if (!status.ok())
702 return status;
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100703
Lalit Maganti2553b802019-05-24 13:25:58 +0100704 for (const auto& desc : pool_.descriptors()) {
Lalit Maganti62211072019-05-10 14:09:58 +0100705 // Convert the full name (e.g. .perfetto.protos.TraceMetrics.SubMetric)
706 // into a function name of the form (TraceMetrics_SubMetric).
707 auto fn_name = desc.full_name().substr(desc.package_name().size() + 1);
708 std::replace(fn_name.begin(), fn_name.end(), '.', '_');
709
Lalit Magantib182d7e2019-05-10 14:13:06 +0100710 std::unique_ptr<metrics::BuildProtoContext> ctx(
711 new metrics::BuildProtoContext());
712 ctx->tp = this;
Lalit Maganti2553b802019-05-24 13:25:58 +0100713 ctx->pool = &pool_;
Lalit Magantib182d7e2019-05-10 14:13:06 +0100714 ctx->desc = &desc;
715
Lalit Maganti62211072019-05-10 14:09:58 +0100716 auto ret = sqlite3_create_function_v2(
Lalit Magantib182d7e2019-05-10 14:13:06 +0100717 *db_, fn_name.c_str(), -1, SQLITE_UTF8, ctx.release(),
718 metrics::BuildProto, nullptr, nullptr, [](void* ptr) {
719 delete static_cast<metrics::BuildProtoContext*>(ptr);
720 });
Lalit Maganti62211072019-05-10 14:09:58 +0100721 if (ret != SQLITE_OK)
722 return util::ErrStatus("%s", sqlite3_errmsg(*db_));
723 }
Lalit Maganti996f5442019-06-21 16:12:58 +0100724 return util::OkStatus();
725}
Lalit Maganti031ad2b2019-05-14 17:37:14 +0100726
Lalit Maganti996f5442019-06-21 16:12:58 +0100727util::Status TraceProcessorImpl::ComputeMetric(
728 const std::vector<std::string>& metric_names,
729 std::vector<uint8_t>* metrics_proto) {
Lalit Maganti2553b802019-05-24 13:25:58 +0100730 auto opt_idx = pool_.FindDescriptorIdx(".perfetto.protos.TraceMetrics");
Lalit Maganti031ad2b2019-05-14 17:37:14 +0100731 if (!opt_idx.has_value())
732 return util::Status("Root metrics proto descriptor not found");
733
Lalit Maganti2553b802019-05-24 13:25:58 +0100734 const auto& root_descriptor = pool_.descriptors()[opt_idx.value()];
735 return metrics::ComputeMetrics(this, metric_names, sql_metrics_,
736 root_descriptor, metrics_proto);
Lalit Magantid9f86b62019-04-08 11:11:51 +0100737}
738
Lalit Maganti77095012019-02-19 13:13:59 +0000739TraceProcessor::IteratorImpl::IteratorImpl(TraceProcessorImpl* trace_processor,
740 sqlite3* db,
741 ScopedStmt stmt,
742 uint32_t column_count,
Lalit Maganti1f067182019-05-09 14:50:05 +0100743 util::Status status,
Lalit Magantiaac2f652019-04-30 12:16:21 +0100744 uint32_t sql_stats_row)
Lalit Maganti77095012019-02-19 13:13:59 +0000745 : trace_processor_(trace_processor),
746 db_(db),
747 stmt_(std::move(stmt)),
748 column_count_(column_count),
Lalit Maganti1f067182019-05-09 14:50:05 +0100749 status_(status),
Lalit Magantiaac2f652019-04-30 12:16:21 +0100750 sql_stats_row_(sql_stats_row) {}
Lalit Maganti77095012019-02-19 13:13:59 +0000751
752TraceProcessor::IteratorImpl::~IteratorImpl() {
753 if (trace_processor_) {
754 auto* its = &trace_processor_->iterators_;
755 auto it = std::find(its->begin(), its->end(), this);
756 PERFETTO_CHECK(it != its->end());
757 its->erase(it);
Lalit Magantiaac2f652019-04-30 12:16:21 +0100758
759 base::TimeNanos t_end = base::GetWallTimeNs();
760 auto* sql_stats = trace_processor_->context_.storage->mutable_sql_stats();
761 sql_stats->RecordQueryEnd(sql_stats_row_, t_end.count());
Lalit Maganti77095012019-02-19 13:13:59 +0000762 }
763}
764
765void TraceProcessor::IteratorImpl::Reset() {
Lalit Maganti1f067182019-05-09 14:50:05 +0100766 *this = IteratorImpl(nullptr, nullptr, ScopedStmt(), 0,
767 util::ErrStatus("Trace processor was deleted"), 0);
Lalit Magantiaac2f652019-04-30 12:16:21 +0100768}
769
770void TraceProcessor::IteratorImpl::RecordFirstNextInSqlStats() {
771 base::TimeNanos t_first_next = base::GetWallTimeNs();
772 auto* sql_stats = trace_processor_->context_.storage->mutable_sql_stats();
773 sql_stats->RecordQueryFirstNext(sql_stats_row_, t_first_next.count());
Lalit Maganti77095012019-02-19 13:13:59 +0000774}
775
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000776} // namespace trace_processor
777} // namespace perfetto