blob: df6fceb97ad9180452ccfec283aef808ce7a99af [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"
Eric Secklerf2de4db2020-02-14 14:17:20 +000026#include "src/trace_processor/additional_modules.h"
Lalit Maganti920f4f92020-02-19 13:45:05 +000027#include "src/trace_processor/experimental_counter_dur_generator.h"
28#include "src/trace_processor/experimental_flamegraph_generator.h"
Mikhail Khokhlov81491b92019-12-19 13:58:22 +000029#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
Lalit Maganti6d1f7b52020-02-27 13:16:44 +000030#include "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h"
31#include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
Lalit Maganti9d538bd2020-03-12 23:48:16 +000032#include "src/trace_processor/importers/gzip/gzip_trace_parser.h"
Lalit Maganti6d1f7b52020-02-27 13:16:44 +000033#include "src/trace_processor/importers/json/json_trace_parser.h"
34#include "src/trace_processor/importers/json/json_trace_tokenizer.h"
35#include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
Hector Dearman93b0b092020-01-09 14:35:04 +000036#include "src/trace_processor/metadata_tracker.h"
Primiano Tucci5cb84f82018-10-31 21:46:36 -070037#include "src/trace_processor/sql_stats_table.h"
Lalit Maganti60732452020-02-04 16:02:53 +000038#include "src/trace_processor/sqlite/span_join_operator_table.h"
Lalit Maganti03d10622019-08-27 14:47:39 +010039#include "src/trace_processor/sqlite/sqlite3_str_split.h"
Lalit Maganti737b3762019-08-26 13:46:37 -070040#include "src/trace_processor/sqlite/sqlite_table.h"
Lalit Maganti1b620a62020-01-30 18:24:53 +000041#include "src/trace_processor/sqlite/sqlite_utils.h"
Lalit Maganti60732452020-02-04 16:02:53 +000042#include "src/trace_processor/sqlite/window_operator_table.h"
Lalit Maganti679b29d2020-01-13 13:26:28 +000043#include "src/trace_processor/sqlite_raw_table.h"
Lalit Maganti05e8c132018-11-09 18:16:12 +000044#include "src/trace_processor/stats_table.h"
Lalit Maganti83b53fa2020-01-13 12:55:36 +000045#include "src/trace_processor/types/variadic.h"
Ioannis Ilkoseff38f52018-10-29 10:37:55 +000046
Eric Secklerc622b8b2019-10-21 09:54:00 +010047#include "src/trace_processor/metrics/metrics.descriptor.h"
48#include "src/trace_processor/metrics/metrics.h"
49#include "src/trace_processor/metrics/sql_metrics.h"
Lalit Maganti26f69bd2019-04-29 18:23:47 +010050
Primiano Tucci02c11762019-08-30 00:57:59 +020051#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010052#include "src/trace_processor/export_json.h"
Lalit Maganti17aa2732019-02-08 15:47:26 +000053#endif
54
Primiano Tuccia1a26de2019-11-12 15:45:19 -080055#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
56#include <cxxabi.h>
57#endif
58
Mikhail Khokhlov8643d1c2019-06-04 12:02:47 +010059// In Android and Chromium tree builds, we don't have the percentile module.
Lalit Maganti17aa2732019-02-08 15:47:26 +000060// Just don't include it.
Primiano Tucci02c11762019-08-30 00:57:59 +020061#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000062// defined in sqlite_src/ext/misc/percentile.c
63extern "C" int sqlite3_percentile_init(sqlite3* db,
64 char** error,
65 const sqlite3_api_routines* api);
Eric Secklera7870e62019-11-01 10:11:58 +000066#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000067
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000068namespace perfetto {
69namespace trace_processor {
Ioannis Ilkos178535e2018-11-05 17:32:45 +000070namespace {
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000071
Primiano Tucci11a79e72019-10-29 22:13:10 +010072const char kAllTablesQuery[] =
73 "SELECT tbl_name, type FROM (SELECT * FROM sqlite_master UNION ALL SELECT "
74 "* FROM sqlite_temp_master)";
75
Ioannis Ilkos7199d552019-03-13 18:35:31 +000076void InitializeSqlite(sqlite3* db) {
77 char* error = nullptr;
78 sqlite3_exec(db, "PRAGMA temp_store=2", 0, 0, &error);
79 if (error) {
80 PERFETTO_FATAL("Error setting pragma temp_store: %s", error);
81 }
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000082 sqlite3_str_split_init(db);
Lalit Maganti17aa2732019-02-08 15:47:26 +000083// In Android tree builds, we don't have the percentile module.
84// Just don't include it.
Primiano Tucci02c11762019-08-30 00:57:59 +020085#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000086 sqlite3_percentile_init(db, &error, nullptr);
Sami Kyostila33668942018-11-13 16:33:32 +000087 if (error) {
Ioannis Ilkos178535e2018-11-05 17:32:45 +000088 PERFETTO_ELOG("Error initializing: %s", error);
Sami Kyostila33668942018-11-13 16:33:32 +000089 sqlite3_free(error);
90 }
Lalit Maganti17aa2732019-02-08 15:47:26 +000091#endif
Sami Kyostila33668942018-11-13 16:33:32 +000092}
93
Lalit Maganti086295b2019-04-04 16:59:19 +010094void BuildBoundsTable(sqlite3* db, std::pair<int64_t, int64_t> bounds) {
95 char* error = nullptr;
96 sqlite3_exec(db, "DELETE FROM trace_bounds", nullptr, nullptr, &error);
97 if (error) {
98 PERFETTO_ELOG("Error deleting from bounds table: %s", error);
99 sqlite3_free(error);
100 return;
101 }
102
103 char* insert_sql = sqlite3_mprintf("INSERT INTO trace_bounds VALUES(%" PRId64
104 ", %" PRId64 ")",
105 bounds.first, bounds.second);
106
107 sqlite3_exec(db, insert_sql, 0, 0, &error);
108 sqlite3_free(insert_sql);
109 if (error) {
110 PERFETTO_ELOG("Error inserting bounds table: %s", error);
111 sqlite3_free(error);
112 }
113}
114
Sami Kyostila33668942018-11-13 16:33:32 +0000115void CreateBuiltinTables(sqlite3* db) {
116 char* error = nullptr;
117 sqlite3_exec(db, "CREATE TABLE perfetto_tables(name STRING)", 0, 0, &error);
118 if (error) {
119 PERFETTO_ELOG("Error initializing: %s", error);
120 sqlite3_free(error);
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000121 }
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000122 sqlite3_exec(db,
123 "CREATE TABLE trace_bounds(start_ts BIG INT, end_ts BIG INT)", 0,
124 0, &error);
125 if (error) {
126 PERFETTO_ELOG("Error initializing: %s", error);
127 sqlite3_free(error);
128 }
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000129
Lalit Maganti086295b2019-04-04 16:59:19 +0100130 // Initialize the bounds table with some data so even before parsing any data,
131 // we still have a valid table.
132 BuildBoundsTable(db, std::make_pair(0, 0));
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000133}
Hector Dearmanc0a29092018-11-08 17:34:23 +0000134
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000135void CreateBuiltinViews(sqlite3* db) {
136 char* error = nullptr;
137 sqlite3_exec(db,
Lalit Maganti809b2f92019-11-07 13:27:26 +0000138 "CREATE VIEW counter_definitions AS "
139 "SELECT "
140 " *, "
Lalit Magantibbc97002019-11-07 17:57:23 +0000141 " id AS counter_id "
Lalit Maganti809b2f92019-11-07 13:27:26 +0000142 "FROM counter_track",
143 0, 0, &error);
144 if (error) {
145 PERFETTO_ELOG("Error initializing: %s", error);
146 sqlite3_free(error);
147 }
148
149 sqlite3_exec(db,
Lalit Maganti69c94442019-11-07 18:59:02 +0000150 "CREATE VIEW counter_values AS "
151 "SELECT "
152 " *, "
153 " track_id as counter_id "
154 "FROM counter",
Lalit Magantibbc97002019-11-07 17:57:23 +0000155 0, 0, &error);
156 if (error) {
157 PERFETTO_ELOG("Error initializing: %s", error);
158 sqlite3_free(error);
159 }
160
161 sqlite3_exec(db,
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000162 "CREATE VIEW counters AS "
Lalit Maganti69c94442019-11-07 18:59:02 +0000163 "SELECT * "
Lalit Magantibbc97002019-11-07 17:57:23 +0000164 "FROM counter_values v "
165 "INNER JOIN counter_track t "
166 "ON v.track_id = t.id "
Lalit Maganti6fbb0ad2019-10-25 14:42:28 +0100167 "ORDER BY ts;",
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000168 0, 0, &error);
169 if (error) {
170 PERFETTO_ELOG("Error initializing: %s", error);
171 sqlite3_free(error);
172 }
Eric Seckler972225e2019-04-18 11:07:12 +0100173
174 sqlite3_exec(db,
175 "CREATE VIEW slice AS "
176 "SELECT "
177 " *, "
Lalit Magantibbc97002019-11-07 17:57:23 +0000178 " category AS cat, "
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000179 " id AS slice_id "
Eric Seckler972225e2019-04-18 11:07:12 +0100180 "FROM internal_slice;",
181 0, 0, &error);
182 if (error) {
183 PERFETTO_ELOG("Error initializing: %s", error);
184 sqlite3_free(error);
185 }
186
Lalit Maganti24b08332019-10-04 12:53:08 +0100187 sqlite3_exec(db,
Lalit Maganti80f566d2020-01-06 13:35:01 +0000188 "CREATE VIEW instants AS "
189 "SELECT "
190 "*, "
191 "0.0 as value "
192 "FROM instant;",
193 0, 0, &error);
Lalit Maganti1b620a62020-01-30 18:24:53 +0000194
195 if (error) {
196 PERFETTO_ELOG("Error initializing: %s", error);
197 sqlite3_free(error);
198 }
199
200 sqlite3_exec(db,
201 "CREATE VIEW sched AS "
202 "SELECT "
203 "*, "
204 "ts + dur as ts_end "
205 "FROM sched_slice;",
206 0, 0, &error);
207
Lalit Maganti80f566d2020-01-06 13:35:01 +0000208 if (error) {
209 PERFETTO_ELOG("Error initializing: %s", error);
210 sqlite3_free(error);
211 }
212
Eric Seckler972225e2019-04-18 11:07:12 +0100213 // Legacy view for "slice" table with a deprecated table name.
214 // TODO(eseckler): Remove this view when all users have switched to "slice".
215 sqlite3_exec(db,
216 "CREATE VIEW slices AS "
217 "SELECT * FROM slice;",
218 0, 0, &error);
219 if (error) {
220 PERFETTO_ELOG("Error initializing: %s", error);
221 sqlite3_free(error);
222 }
Lalit Magantieac7fff2020-01-10 16:42:54 +0000223
224 sqlite3_exec(db,
225 "CREATE VIEW thread AS "
226 "SELECT "
227 "id as utid, "
228 "* "
229 "FROM internal_thread;",
230 0, 0, &error);
231 if (error) {
232 PERFETTO_ELOG("Error initializing: %s", error);
233 sqlite3_free(error);
234 }
235
236 sqlite3_exec(db,
237 "CREATE VIEW process AS "
238 "SELECT "
239 "id as upid, "
240 "* "
241 "FROM internal_process;",
242 0, 0, &error);
243 if (error) {
244 PERFETTO_ELOG("Error initializing: %s", error);
245 sqlite3_free(error);
246 }
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000247}
248
Primiano Tucci02c11762019-08-30 00:57:59 +0200249#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100250void ExportJson(sqlite3_context* ctx, int /*argc*/, sqlite3_value** argv) {
251 TraceStorage* storage = static_cast<TraceStorage*>(sqlite3_user_data(ctx));
Eric Seckler37ad6af2019-10-08 15:51:14 +0100252 FILE* output;
253 if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
254 // Assume input is an FD.
255 output = fdopen(sqlite3_value_int(argv[0]), "w");
256 if (!output) {
257 sqlite3_result_error(ctx, "Couldn't open output file from given FD", -1);
258 return;
259 }
260 } else {
261 const char* filename =
262 reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
263 output = fopen(filename, "w");
264 if (!output) {
265 sqlite3_result_error(ctx, "Couldn't open output file", -1);
266 return;
267 }
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100268 }
269
Eric Seckler7fb1d232019-10-23 14:42:43 +0100270 util::Status result = json::ExportJson(storage, output);
271 if (!result.ok()) {
272 sqlite3_result_error(ctx, result.message().c_str(), -1);
273 return;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100274 }
275}
276
277void CreateJsonExportFunction(TraceStorage* ts, sqlite3* db) {
278 auto ret = sqlite3_create_function_v2(db, "EXPORT_JSON", 1, SQLITE_UTF8, ts,
279 ExportJson, nullptr, nullptr,
280 sqlite_utils::kSqliteStatic);
281 if (ret) {
282 PERFETTO_ELOG("Error initializing EXPORT_JSON");
283 }
284}
285#endif
286
Lalit Maganti062c8f82019-10-03 20:11:29 +0100287void Hash(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
288 base::Hash hash;
289 for (int i = 0; i < argc; ++i) {
290 sqlite3_value* value = argv[i];
291 switch (sqlite3_value_type(value)) {
292 case SQLITE_INTEGER:
293 hash.Update(sqlite3_value_int64(value));
294 break;
295 case SQLITE_TEXT: {
296 const char* ptr =
297 reinterpret_cast<const char*>(sqlite3_value_text(value));
298 hash.Update(ptr, strlen(ptr));
299 break;
300 }
301 default:
302 sqlite3_result_error(ctx, "Unsupported type of arg passed to HASH", -1);
303 return;
304 }
305 }
306 sqlite3_result_int64(ctx, static_cast<int64_t>(hash.digest()));
307}
308
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000309void Demangle(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
310 if (argc != 1) {
311 sqlite3_result_error(ctx, "Unsupported number of arg passed to DEMANGLE",
312 -1);
313 return;
314 }
315 sqlite3_value* value = argv[0];
316 if (sqlite3_value_type(value) != SQLITE_TEXT) {
317 sqlite3_result_error(ctx, "Unsupported type of arg passed to DEMANGLE", -1);
318 return;
319 }
320 const char* ptr = reinterpret_cast<const char*>(sqlite3_value_text(value));
Primiano Tuccia1a26de2019-11-12 15:45:19 -0800321#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000322 int ignored = 0;
323 // This memory was allocated by malloc and will be passed to SQLite to free.
324 char* demangled_name = abi::__cxa_demangle(ptr, nullptr, nullptr, &ignored);
325 if (!demangled_name) {
326 sqlite3_result_null(ctx);
327 return;
328 }
329 sqlite3_result_text(ctx, demangled_name, -1, free);
Primiano Tuccia1a26de2019-11-12 15:45:19 -0800330#else
331 sqlite3_result_text(ctx, ptr, -1, sqlite_utils::kSqliteTransient);
332#endif
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000333}
334
Pascal Muetschard7e476092020-01-15 16:41:30 -0800335void LastNonNullStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
336 if (argc != 1) {
337 sqlite3_result_error(ctx,
338 "Unsupported number of args passed to LAST_NON_NULL",
339 -1);
340 return;
341 }
342 sqlite3_value* value = argv[0];
343 if (sqlite3_value_type(value) == SQLITE_NULL) {
344 return;
345 }
346 sqlite3_value** ptr = reinterpret_cast<sqlite3_value**>(
347 sqlite3_aggregate_context(ctx, sizeof(sqlite3_value*)));
348 if (ptr) {
349 if (*ptr != nullptr) {
350 sqlite3_value_free(*ptr);
351 }
352 *ptr = sqlite3_value_dup(value);
353 }
354}
355
356void LastNonNullInverse(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
357 // Do nothing.
358 base::ignore_result(ctx);
359 base::ignore_result(argc);
360 base::ignore_result(argv);
361}
362
363void LastNonNullValue(sqlite3_context* ctx) {
364 sqlite3_value** ptr =
365 reinterpret_cast<sqlite3_value**>(sqlite3_aggregate_context(ctx, 0));
366 if (!ptr || !*ptr) {
367 sqlite3_result_null(ctx);
368 } else {
369 sqlite3_result_value(ctx, *ptr);
370 }
371}
372
373void LastNonNullFinal(sqlite3_context* ctx) {
374 sqlite3_value** ptr =
375 reinterpret_cast<sqlite3_value**>(sqlite3_aggregate_context(ctx, 0));
376 if (!ptr || !*ptr) {
377 sqlite3_result_null(ctx);
378 } else {
379 sqlite3_result_value(ctx, *ptr);
380 sqlite3_value_free(*ptr);
381 }
382}
383
Lalit Maganti062c8f82019-10-03 20:11:29 +0100384void CreateHashFunction(sqlite3* db) {
385 auto ret = sqlite3_create_function_v2(
386 db, "HASH", -1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &Hash,
387 nullptr, nullptr, nullptr);
388 if (ret) {
389 PERFETTO_ELOG("Error initializing HASH");
390 }
391}
392
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000393void CreateDemangledNameFunction(sqlite3* db) {
394 auto ret = sqlite3_create_function_v2(
395 db, "DEMANGLE", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &Demangle,
396 nullptr, nullptr, nullptr);
397 if (ret != SQLITE_OK) {
398 PERFETTO_ELOG("Error initializing DEMANGLE: %s", sqlite3_errmsg(db));
399 }
400}
401
Pascal Muetschard7e476092020-01-15 16:41:30 -0800402void CreateLastNonNullFunction(sqlite3* db) {
403 auto ret = sqlite3_create_window_function(
404 db, "LAST_NON_NULL", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr,
405 &LastNonNullStep, &LastNonNullFinal, &LastNonNullValue,
406 &LastNonNullInverse, nullptr);
407 if (ret) {
408 PERFETTO_ELOG("Error initializing LAST_NON_NULL");
409 }
410}
411
Lalit Maganti2553b802019-05-24 13:25:58 +0100412void SetupMetrics(TraceProcessor* tp,
413 sqlite3* db,
Lalit Maganti2553b802019-05-24 13:25:58 +0100414 std::vector<metrics::SqlMetricFile>* sql_metrics) {
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100415 tp->ExtendMetricsProto(kMetricsDescriptor.data(), kMetricsDescriptor.size());
416
Lalit Maganti2553b802019-05-24 13:25:58 +0100417 for (const auto& file_to_sql : metrics::sql_metrics::kFileToSql) {
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100418 tp->RegisterMetric(file_to_sql.path, file_to_sql.sql);
Lalit Maganti2553b802019-05-24 13:25:58 +0100419 }
420
421 {
422 std::unique_ptr<metrics::RunMetricContext> ctx(
423 new metrics::RunMetricContext());
424 ctx->tp = tp;
425 ctx->metrics = sql_metrics;
426 auto ret = sqlite3_create_function_v2(
427 db, "RUN_METRIC", -1, SQLITE_UTF8, ctx.release(), metrics::RunMetric,
428 nullptr, nullptr,
429 [](void* ptr) { delete static_cast<metrics::RunMetricContext*>(ptr); });
430 if (ret)
431 PERFETTO_ELOG("Error initializing RUN_METRIC");
432 }
433
434 {
435 auto ret = sqlite3_create_function_v2(
436 db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr,
437 metrics::RepeatedFieldStep, metrics::RepeatedFieldFinal, nullptr);
438 if (ret)
439 PERFETTO_ELOG("Error initializing RepeatedField");
440 }
441}
Oystein Eftevaag477bbff2020-01-27 11:07:49 -0800442
443void EnsureSqliteInitialized() {
444 // sqlite3_initialize isn't actually thread-safe despite being documented
445 // as such; we need to make sure multiple TraceProcessorImpl instances don't
446 // call it concurrently and only gets called once per process, instead.
Lalit Maganti1e5630e2020-01-29 12:34:14 +0000447 static bool init_once = [] { return sqlite3_initialize() == SQLITE_OK; }();
Oystein Eftevaag477bbff2020-01-27 11:07:49 -0800448 PERFETTO_CHECK(init_once);
449}
450
Hector Dearmanc0a29092018-11-08 17:34:23 +0000451} // namespace
452
Eric Secklera7870e62019-11-01 10:11:58 +0000453TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
454 : TraceProcessorStorageImpl(cfg) {
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000455 context_.fuchsia_trace_tokenizer.reset(new FuchsiaTraceTokenizer(&context_));
456 context_.fuchsia_trace_parser.reset(new FuchsiaTraceParser(&context_));
457
458 context_.systrace_trace_parser.reset(new SystraceTraceParser(&context_));
459
Lalit Maganti9d538bd2020-03-12 23:48:16 +0000460 if (gzip_utils::IsGzipSupported())
461 context_.gzip_trace_parser.reset(new GzipTraceParser(&context_));
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000462
463#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
464 context_.json_trace_tokenizer.reset(new JsonTraceTokenizer(&context_));
465 context_.json_trace_parser.reset(new JsonTraceParser(&context_));
466#endif
467
Mikhail Khokhlov692087e2019-12-11 10:53:45 +0000468 RegisterAdditionalModules(&context_);
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000469
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000470 sqlite3* db = nullptr;
Oystein Eftevaag477bbff2020-01-27 11:07:49 -0800471 EnsureSqliteInitialized();
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000472 PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
Ioannis Ilkos7199d552019-03-13 18:35:31 +0000473 InitializeSqlite(db);
Sami Kyostila33668942018-11-13 16:33:32 +0000474 CreateBuiltinTables(db);
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000475 CreateBuiltinViews(db);
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000476 db_.reset(std::move(db));
477
Primiano Tucci02c11762019-08-30 00:57:59 +0200478#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100479 CreateJsonExportFunction(this->context_.storage.get(), db);
480#endif
Lalit Maganti062c8f82019-10-03 20:11:29 +0100481 CreateHashFunction(db);
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000482 CreateDemangledNameFunction(db);
Pascal Muetschard7e476092020-01-15 16:41:30 -0800483 CreateLastNonNullFunction(db);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100484
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100485 SetupMetrics(this, *db_, &sql_metrics_);
Lalit Maganti2553b802019-05-24 13:25:58 +0100486
Lalit Maganti65800eb2020-01-30 15:18:59 +0000487 // Setup the query cache.
488 query_cache_.reset(new QueryCache());
489
Lalit Maganti786cc922019-09-06 16:04:32 +0100490 const TraceStorage* storage = context_.storage.get();
Lalit Maganti809b2f92019-11-07 13:27:26 +0000491
Lalit Maganti679b29d2020-01-13 13:26:28 +0000492 SqlStatsTable::RegisterTable(*db_, storage);
Lalit Maganti679b29d2020-01-13 13:26:28 +0000493 StatsTable::RegisterTable(*db_, storage);
494
Lalit Maganti8a39fae2020-01-20 17:22:10 +0000495 // Operator tables.
496 SpanJoinOperatorTable::RegisterTable(*db_, storage);
497 WindowOperatorTable::RegisterTable(*db_, storage);
498
Lalit Maganti679b29d2020-01-13 13:26:28 +0000499 // New style tables but with some custom logic.
Lalit Maganti65800eb2020-01-30 15:18:59 +0000500 SqliteRawTable::RegisterTable(*db_, query_cache_.get(),
501 context_.storage.get());
Lalit Maganti920f4f92020-02-19 13:45:05 +0000502
503 // Tables dynamically generated at query time.
504 RegisterDynamicTable(std::unique_ptr<ExperimentalFlamegraphGenerator>(
505 new ExperimentalFlamegraphGenerator(&context_)));
506 RegisterDynamicTable(std::unique_ptr<ExperimentalCounterDurGenerator>(
507 new ExperimentalCounterDurGenerator(storage->counter_table())));
Lalit Maganti679b29d2020-01-13 13:26:28 +0000508
509 // New style db-backed tables.
Lalit Maganti65800eb2020-01-30 15:18:59 +0000510 RegisterDbTable(storage->arg_table());
511 RegisterDbTable(storage->thread_table());
512 RegisterDbTable(storage->process_table());
Lalit Maganti1908e262020-01-09 14:33:19 +0000513
Lalit Maganti65800eb2020-01-30 15:18:59 +0000514 RegisterDbTable(storage->slice_table());
Lalit Maganti1b620a62020-01-30 18:24:53 +0000515 RegisterDbTable(storage->sched_slice_table());
Lalit Maganti65800eb2020-01-30 15:18:59 +0000516 RegisterDbTable(storage->instant_table());
517 RegisterDbTable(storage->gpu_slice_table());
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000518
Lalit Maganti65800eb2020-01-30 15:18:59 +0000519 RegisterDbTable(storage->track_table());
520 RegisterDbTable(storage->thread_track_table());
521 RegisterDbTable(storage->process_track_table());
522 RegisterDbTable(storage->gpu_track_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000523
Lalit Maganti65800eb2020-01-30 15:18:59 +0000524 RegisterDbTable(storage->counter_table());
Lalit Maganti4b3b3ad2019-12-04 19:27:35 +0000525
Lalit Maganti65800eb2020-01-30 15:18:59 +0000526 RegisterDbTable(storage->counter_track_table());
527 RegisterDbTable(storage->process_counter_track_table());
528 RegisterDbTable(storage->thread_counter_track_table());
529 RegisterDbTable(storage->cpu_counter_track_table());
530 RegisterDbTable(storage->irq_counter_track_table());
531 RegisterDbTable(storage->softirq_counter_track_table());
532 RegisterDbTable(storage->gpu_counter_track_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000533
Lalit Maganti65800eb2020-01-30 15:18:59 +0000534 RegisterDbTable(storage->heap_graph_object_table());
535 RegisterDbTable(storage->heap_graph_reference_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000536
Lalit Maganti65800eb2020-01-30 15:18:59 +0000537 RegisterDbTable(storage->symbol_table());
538 RegisterDbTable(storage->heap_profile_allocation_table());
539 RegisterDbTable(storage->cpu_profile_stack_sample_table());
540 RegisterDbTable(storage->stack_profile_callsite_table());
541 RegisterDbTable(storage->stack_profile_mapping_table());
542 RegisterDbTable(storage->stack_profile_frame_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000543
Lalit Maganti65800eb2020-01-30 15:18:59 +0000544 RegisterDbTable(storage->android_log_table());
Lalit Magantif1ab24f2020-01-07 17:42:26 +0000545
Lalit Maganti65800eb2020-01-30 15:18:59 +0000546 RegisterDbTable(storage->vulkan_memory_allocations_table());
Lalit Magantiededb0e2020-01-08 12:50:34 +0000547
Lalit Maganti65800eb2020-01-30 15:18:59 +0000548 RegisterDbTable(storage->metadata_table());
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000549}
550
Lalit Maganti77095012019-02-19 13:13:59 +0000551TraceProcessorImpl::~TraceProcessorImpl() {
552 for (auto* it : iterators_)
553 it->Reset();
554}
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000555
Lalit Maganti1f067182019-05-09 14:50:05 +0100556util::Status TraceProcessorImpl::Parse(std::unique_ptr<uint8_t[]> data,
557 size_t size) {
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100558 bytes_parsed_ += size;
Eric Secklera7870e62019-11-01 10:11:58 +0000559 return TraceProcessorStorageImpl::Parse(std::move(data), size);
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000560}
561
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100562std::string TraceProcessorImpl::GetCurrentTraceName() {
563 if (current_trace_name_.empty())
564 return "";
565 auto size = " (" + std::to_string(bytes_parsed_ / 1024 / 1024) + " MB)";
566 return current_trace_name_ + size;
567}
568
569void TraceProcessorImpl::SetCurrentTraceName(const std::string& name) {
570 current_trace_name_ = name;
571}
572
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000573void TraceProcessorImpl::NotifyEndOfFile() {
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100574 if (current_trace_name_.empty())
575 current_trace_name_ = "Unnamed trace";
576
Eric Secklera7870e62019-11-01 10:11:58 +0000577 TraceProcessorStorageImpl::NotifyEndOfFile();
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700578
Mikhail Khokhlov81491b92019-12-19 13:58:22 +0000579 SchedEventTracker::GetOrCreate(&context_)->FlushPendingEvents();
Hector Dearman93b0b092020-01-09 14:35:04 +0000580 context_.metadata_tracker->SetMetadata(
581 metadata::trace_size_bytes,
582 Variadic::Integer(static_cast<int64_t>(bytes_parsed_)));
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000583 BuildBoundsTable(*db_, context_.storage->GetTraceTimestampBoundsNs());
Primiano Tucci11a79e72019-10-29 22:13:10 +0100584
585 // Create a snapshot of all tables and views created so far. This is so later
586 // we can drop all extra tables created by the UI and reset to the original
587 // state (see RestoreInitialTables).
588 initial_tables_.clear();
589 auto it = ExecuteQuery(kAllTablesQuery);
590 while (it.Next()) {
591 auto value = it.Get(0);
592 PERFETTO_CHECK(value.type == SqlValue::Type::kString);
593 initial_tables_.push_back(value.string_value);
594 }
595}
596
597size_t TraceProcessorImpl::RestoreInitialTables() {
598 std::vector<std::pair<std::string, std::string>> deletion_list;
599 std::string msg = "Resetting DB to initial state, deleting table/views:";
600 for (auto it = ExecuteQuery(kAllTablesQuery); it.Next();) {
601 std::string name(it.Get(0).string_value);
602 std::string type(it.Get(1).string_value);
603 if (std::find(initial_tables_.begin(), initial_tables_.end(), name) ==
604 initial_tables_.end()) {
605 msg += " " + name;
606 deletion_list.push_back(std::make_pair(type, name));
607 }
608 }
609
610 PERFETTO_LOG("%s", msg.c_str());
611 for (const auto& tn : deletion_list) {
612 std::string query = "DROP " + tn.first + " " + tn.second;
613 auto it = ExecuteQuery(query);
614 while (it.Next()) {
615 }
Primiano Tucci1b4c8fc2020-01-15 22:29:42 +0000616 // Index deletion can legitimately fail. If one creates an index "i" on a
617 // table "t" but issues the deletion in the order (t, i), the DROP index i
618 // will fail with "no such index" because deleting the table "t"
619 // automatically deletes all associated indexes.
620 if (!it.Status().ok() && tn.first != "index")
621 PERFETTO_FATAL("%s -> %s", query.c_str(), it.Status().c_message());
Primiano Tucci11a79e72019-10-29 22:13:10 +0100622 }
623 return deletion_list.size();
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000624}
625
Lalit Maganti77095012019-02-19 13:13:59 +0000626TraceProcessor::Iterator TraceProcessorImpl::ExecuteQuery(
Lalit Magantiaac2f652019-04-30 12:16:21 +0100627 const std::string& sql,
628 int64_t time_queued) {
Lalit Maganti77095012019-02-19 13:13:59 +0000629 sqlite3_stmt* raw_stmt;
Lalit Maganti73b1a0a2019-04-08 13:51:14 +0100630 int err = sqlite3_prepare_v2(*db_, sql.c_str(), static_cast<int>(sql.size()),
Lalit Maganti77095012019-02-19 13:13:59 +0000631 &raw_stmt, nullptr);
Lalit Maganti1f067182019-05-09 14:50:05 +0100632 util::Status status;
Lalit Maganti06acc022019-04-03 16:02:15 +0100633 uint32_t col_count = 0;
634 if (err != SQLITE_OK) {
Lalit Maganti7ee6abb2019-05-09 17:57:32 +0100635 status = util::ErrStatus("%s", sqlite3_errmsg(*db_));
Lalit Maganti77095012019-02-19 13:13:59 +0000636 } else {
637 col_count = static_cast<uint32_t>(sqlite3_column_count(raw_stmt));
638 }
Lalit Magantiaac2f652019-04-30 12:16:21 +0100639
640 base::TimeNanos t_start = base::GetWallTimeNs();
641 uint32_t sql_stats_row =
642 context_.storage->mutable_sql_stats()->RecordQueryBegin(sql, time_queued,
643 t_start.count());
644
645 std::unique_ptr<IteratorImpl> impl(new IteratorImpl(
Lalit Maganti1f067182019-05-09 14:50:05 +0100646 this, *db_, ScopedStmt(raw_stmt), col_count, status, sql_stats_row));
Lalit Maganti77095012019-02-19 13:13:59 +0000647 iterators_.emplace_back(impl.get());
648 return TraceProcessor::Iterator(std::move(impl));
649}
650
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000651void TraceProcessorImpl::InterruptQuery() {
652 if (!db_)
653 return;
654 query_interrupted_.store(true);
655 sqlite3_interrupt(db_.get());
656}
657
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100658util::Status TraceProcessorImpl::RegisterMetric(const std::string& path,
659 const std::string& sql) {
Lalit Magantif9d80302019-06-19 12:48:25 +0100660 std::string stripped_sql;
661 for (base::StringSplitter sp(sql, '\n'); sp.Next();) {
662 if (strncmp(sp.cur_token(), "--", 2) != 0) {
663 stripped_sql.append(sp.cur_token());
664 stripped_sql.push_back('\n');
665 }
666 }
667
668 // Check if the metric with the given path already exists and if it does, just
669 // update the SQL associated with it.
670 auto it = std::find_if(
671 sql_metrics_.begin(), sql_metrics_.end(),
672 [&path](const metrics::SqlMetricFile& m) { return m.path == path; });
673 if (it != sql_metrics_.end()) {
674 it->sql = stripped_sql;
675 return util::OkStatus();
676 }
677
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100678 auto sep_idx = path.rfind("/");
679 std::string basename =
680 sep_idx == std::string::npos ? path : path.substr(sep_idx + 1);
681
682 auto sql_idx = basename.rfind(".sql");
683 if (sql_idx == std::string::npos) {
684 return util::ErrStatus("Unable to find .sql extension for metric");
685 }
686 auto no_ext_name = basename.substr(0, sql_idx);
687
688 metrics::SqlMetricFile metric;
689 metric.path = path;
690 metric.proto_field_name = no_ext_name;
691 metric.output_table_name = no_ext_name + "_output";
Lalit Magantica4d5142019-05-28 13:25:47 +0100692 metric.sql = stripped_sql;
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100693 sql_metrics_.emplace_back(metric);
694 return util::OkStatus();
695}
696
697util::Status TraceProcessorImpl::ExtendMetricsProto(const uint8_t* data,
698 size_t size) {
Lalit Maganti996f5442019-06-21 16:12:58 +0100699 util::Status status = pool_.AddFromFileDescriptorSet(data, size);
700 if (!status.ok())
701 return status;
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100702
Lalit Maganti2553b802019-05-24 13:25:58 +0100703 for (const auto& desc : pool_.descriptors()) {
Lalit Maganti62211072019-05-10 14:09:58 +0100704 // Convert the full name (e.g. .perfetto.protos.TraceMetrics.SubMetric)
705 // into a function name of the form (TraceMetrics_SubMetric).
706 auto fn_name = desc.full_name().substr(desc.package_name().size() + 1);
707 std::replace(fn_name.begin(), fn_name.end(), '.', '_');
708
Lalit Magantib182d7e2019-05-10 14:13:06 +0100709 std::unique_ptr<metrics::BuildProtoContext> ctx(
710 new metrics::BuildProtoContext());
711 ctx->tp = this;
Lalit Maganti2553b802019-05-24 13:25:58 +0100712 ctx->pool = &pool_;
Lalit Magantib182d7e2019-05-10 14:13:06 +0100713 ctx->desc = &desc;
714
Lalit Maganti62211072019-05-10 14:09:58 +0100715 auto ret = sqlite3_create_function_v2(
Lalit Magantib182d7e2019-05-10 14:13:06 +0100716 *db_, fn_name.c_str(), -1, SQLITE_UTF8, ctx.release(),
717 metrics::BuildProto, nullptr, nullptr, [](void* ptr) {
718 delete static_cast<metrics::BuildProtoContext*>(ptr);
719 });
Lalit Maganti62211072019-05-10 14:09:58 +0100720 if (ret != SQLITE_OK)
721 return util::ErrStatus("%s", sqlite3_errmsg(*db_));
722 }
Lalit Maganti996f5442019-06-21 16:12:58 +0100723 return util::OkStatus();
724}
Lalit Maganti031ad2b2019-05-14 17:37:14 +0100725
Lalit Maganti996f5442019-06-21 16:12:58 +0100726util::Status TraceProcessorImpl::ComputeMetric(
727 const std::vector<std::string>& metric_names,
728 std::vector<uint8_t>* metrics_proto) {
Lalit Maganti2553b802019-05-24 13:25:58 +0100729 auto opt_idx = pool_.FindDescriptorIdx(".perfetto.protos.TraceMetrics");
Lalit Maganti031ad2b2019-05-14 17:37:14 +0100730 if (!opt_idx.has_value())
731 return util::Status("Root metrics proto descriptor not found");
732
Lalit Maganti2553b802019-05-24 13:25:58 +0100733 const auto& root_descriptor = pool_.descriptors()[opt_idx.value()];
734 return metrics::ComputeMetrics(this, metric_names, sql_metrics_,
735 root_descriptor, metrics_proto);
Lalit Magantid9f86b62019-04-08 11:11:51 +0100736}
737
Lalit Maganti77095012019-02-19 13:13:59 +0000738TraceProcessor::IteratorImpl::IteratorImpl(TraceProcessorImpl* trace_processor,
739 sqlite3* db,
740 ScopedStmt stmt,
741 uint32_t column_count,
Lalit Maganti1f067182019-05-09 14:50:05 +0100742 util::Status status,
Lalit Magantiaac2f652019-04-30 12:16:21 +0100743 uint32_t sql_stats_row)
Lalit Maganti77095012019-02-19 13:13:59 +0000744 : trace_processor_(trace_processor),
745 db_(db),
746 stmt_(std::move(stmt)),
747 column_count_(column_count),
Lalit Maganti1f067182019-05-09 14:50:05 +0100748 status_(status),
Lalit Magantiaac2f652019-04-30 12:16:21 +0100749 sql_stats_row_(sql_stats_row) {}
Lalit Maganti77095012019-02-19 13:13:59 +0000750
751TraceProcessor::IteratorImpl::~IteratorImpl() {
752 if (trace_processor_) {
753 auto* its = &trace_processor_->iterators_;
754 auto it = std::find(its->begin(), its->end(), this);
755 PERFETTO_CHECK(it != its->end());
756 its->erase(it);
Lalit Magantiaac2f652019-04-30 12:16:21 +0100757
758 base::TimeNanos t_end = base::GetWallTimeNs();
759 auto* sql_stats = trace_processor_->context_.storage->mutable_sql_stats();
760 sql_stats->RecordQueryEnd(sql_stats_row_, t_end.count());
Lalit Maganti77095012019-02-19 13:13:59 +0000761 }
762}
763
764void TraceProcessor::IteratorImpl::Reset() {
Lalit Maganti1f067182019-05-09 14:50:05 +0100765 *this = IteratorImpl(nullptr, nullptr, ScopedStmt(), 0,
766 util::ErrStatus("Trace processor was deleted"), 0);
Lalit Magantiaac2f652019-04-30 12:16:21 +0100767}
768
769void TraceProcessor::IteratorImpl::RecordFirstNextInSqlStats() {
770 base::TimeNanos t_first_next = base::GetWallTimeNs();
771 auto* sql_stats = trace_processor_->context_.storage->mutable_sql_stats();
772 sql_stats->RecordQueryFirstNext(sql_stats_row_, t_first_next.count());
Lalit Maganti77095012019-02-19 13:13:59 +0000773}
774
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000775} // namespace trace_processor
776} // namespace perfetto