blob: f942406eb164d8653c39a276ca2a99c866ac8fe3 [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
Hector Dearmanc0a29092018-11-08 17:34:23 +000019#include <algorithm>
Primiano Tucci58d2dc62021-06-24 16:03:24 +010020#include <cinttypes>
Lalit Maganti82517672021-11-04 23:39:15 +000021#include <memory>
Ioannis Ilkoseff38f52018-10-29 10:37:55 +000022
Lalit Maganti77095012019-02-19 13:13:59 +000023#include "perfetto/base/logging.h"
Lalit Maganti82517672021-11-04 23:39:15 +000024#include "perfetto/base/status.h"
Eric Seckler83dcc8c2019-08-21 12:18:43 +010025#include "perfetto/base/time.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010026#include "perfetto/ext/base/string_splitter.h"
27#include "perfetto/ext/base/string_utils.h"
Stephen Nuskodd7f6dc2020-11-26 17:04:08 -050028#include "src/trace_processor/dynamic/ancestor_generator.h"
Andrii824107d2020-09-29 10:13:36 +030029#include "src/trace_processor/dynamic/connected_flow_generator.h"
Zaina Al-Mashni5ed83f92021-09-09 09:08:38 +000030#include "src/trace_processor/dynamic/descendant_generator.h"
Lalit Maganti1f4712b2020-04-14 21:01:13 +010031#include "src/trace_processor/dynamic/describe_slice_generator.h"
Ryanddeb3b12021-04-12 15:55:17 +010032#include "src/trace_processor/dynamic/experimental_annotated_stack_generator.h"
Lalit Maganti1f4712b2020-04-14 21:01:13 +010033#include "src/trace_processor/dynamic/experimental_counter_dur_generator.h"
34#include "src/trace_processor/dynamic/experimental_flamegraph_generator.h"
Lalit Maganti40fbe8e2021-06-10 16:21:25 +010035#include "src/trace_processor/dynamic/experimental_flat_slice_generator.h"
Lalit Magantic59b1bc2020-07-28 16:36:58 +010036#include "src/trace_processor/dynamic/experimental_sched_upid_generator.h"
Hector Dearman5b523762020-04-16 10:36:32 +010037#include "src/trace_processor/dynamic/experimental_slice_layout_generator.h"
Lalit Maganti2fc5db22020-08-13 15:02:47 +010038#include "src/trace_processor/dynamic/thread_state_generator.h"
Lalit Maganti0bfeb972020-03-14 03:57:30 +000039#include "src/trace_processor/export_json.h"
Lalit Maganti60af4ef2020-04-15 14:27:09 +010040#include "src/trace_processor/importers/additional_modules.h"
Mikhail Khokhlov81491b92019-12-19 13:58:22 +000041#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
Lalit Maganti6d1f7b52020-02-27 13:16:44 +000042#include "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h"
43#include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
Lalit Maganti9d538bd2020-03-12 23:48:16 +000044#include "src/trace_processor/importers/gzip/gzip_trace_parser.h"
Lalit Maganti6d1f7b52020-02-27 13:16:44 +000045#include "src/trace_processor/importers/json/json_trace_parser.h"
46#include "src/trace_processor/importers/json/json_trace_tokenizer.h"
Lalit Maganti05819e22020-04-14 21:01:38 +010047#include "src/trace_processor/importers/proto/metadata_tracker.h"
Lalit Maganti6d1f7b52020-02-27 13:16:44 +000048#include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
Primiano Tucci4e01f632020-06-11 17:03:05 +010049#include "src/trace_processor/iterator_impl.h"
Lalit Maganti82517672021-11-04 23:39:15 +000050#include "src/trace_processor/sqlite/register_function.h"
Lalit Maganti60732452020-02-04 16:02:53 +000051#include "src/trace_processor/sqlite/span_join_operator_table.h"
Lalit Maganti655adae2020-04-14 21:01:25 +010052#include "src/trace_processor/sqlite/sql_stats_table.h"
Lalit Maganti03d10622019-08-27 14:47:39 +010053#include "src/trace_processor/sqlite/sqlite3_str_split.h"
Lalit Maganti655adae2020-04-14 21:01:25 +010054#include "src/trace_processor/sqlite/sqlite_raw_table.h"
Lalit Maganti737b3762019-08-26 13:46:37 -070055#include "src/trace_processor/sqlite/sqlite_table.h"
Lalit Maganti1b620a62020-01-30 18:24:53 +000056#include "src/trace_processor/sqlite/sqlite_utils.h"
Lalit Maganti655adae2020-04-14 21:01:25 +010057#include "src/trace_processor/sqlite/stats_table.h"
Lalit Maganti60732452020-02-04 16:02:53 +000058#include "src/trace_processor/sqlite/window_operator_table.h"
Lalit Maganti427b8332020-05-27 16:09:45 +010059#include "src/trace_processor/tp_metatrace.h"
Lalit Maganti83b53fa2020-01-13 12:55:36 +000060#include "src/trace_processor/types/variadic.h"
Deepanjan Roy1e048012020-09-23 12:49:04 -040061#include "src/trace_processor/util/protozero_to_text.h"
Lalit Maganti82517672021-11-04 23:39:15 +000062#include "src/trace_processor/util/status_macros.h"
Ioannis Ilkoseff38f52018-10-29 10:37:55 +000063
Lalit Maganti427b8332020-05-27 16:09:45 +010064#include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
Primiano Tucci1d51ae32020-05-28 09:41:21 +010065#include "protos/perfetto/trace/trace.pbzero.h"
Lalit Maganti427b8332020-05-27 16:09:45 +010066#include "protos/perfetto/trace/trace_packet.pbzero.h"
67
Deepanjan Royf4da5092020-07-15 17:59:04 -040068#include "src/trace_processor/metrics/chrome/all_chrome_metrics.descriptor.h"
Eric Secklerc622b8b2019-10-21 09:54:00 +010069#include "src/trace_processor/metrics/metrics.descriptor.h"
70#include "src/trace_processor/metrics/metrics.h"
71#include "src/trace_processor/metrics/sql_metrics.h"
Lalit Maganti26f69bd2019-04-29 18:23:47 +010072
Primiano Tuccia1a26de2019-11-12 15:45:19 -080073#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
74#include <cxxabi.h>
75#endif
76
Mikhail Khokhlov8643d1c2019-06-04 12:02:47 +010077// In Android and Chromium tree builds, we don't have the percentile module.
Lalit Maganti17aa2732019-02-08 15:47:26 +000078// Just don't include it.
Primiano Tucci02c11762019-08-30 00:57:59 +020079#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000080// defined in sqlite_src/ext/misc/percentile.c
81extern "C" int sqlite3_percentile_init(sqlite3* db,
82 char** error,
83 const sqlite3_api_routines* api);
Eric Secklera7870e62019-11-01 10:11:58 +000084#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000085
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000086namespace perfetto {
87namespace trace_processor {
Ioannis Ilkos178535e2018-11-05 17:32:45 +000088namespace {
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000089
Primiano Tucci11a79e72019-10-29 22:13:10 +010090const char kAllTablesQuery[] =
91 "SELECT tbl_name, type FROM (SELECT * FROM sqlite_master UNION ALL SELECT "
92 "* FROM sqlite_temp_master)";
93
Lalit Maganti82517672021-11-04 23:39:15 +000094template <typename SqlFunction, typename Ptr = typename SqlFunction::Context*>
95void RegisterFunction(sqlite3* db,
96 const char* name,
97 int argc,
98 Ptr context = nullptr,
99 bool deterministic = true) {
100 auto status = RegisterSqlFunction<SqlFunction>(
101 db, name, argc, std::move(context), deterministic);
102 if (!status.ok())
103 PERFETTO_ELOG("%s", status.c_message());
104}
105
Ioannis Ilkos7199d552019-03-13 18:35:31 +0000106void InitializeSqlite(sqlite3* db) {
107 char* error = nullptr;
108 sqlite3_exec(db, "PRAGMA temp_store=2", 0, 0, &error);
109 if (error) {
110 PERFETTO_FATAL("Error setting pragma temp_store: %s", error);
111 }
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +0000112 sqlite3_str_split_init(db);
Lalit Maganti17aa2732019-02-08 15:47:26 +0000113// In Android tree builds, we don't have the percentile module.
114// Just don't include it.
Primiano Tucci02c11762019-08-30 00:57:59 +0200115#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000116 sqlite3_percentile_init(db, &error, nullptr);
Sami Kyostila33668942018-11-13 16:33:32 +0000117 if (error) {
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000118 PERFETTO_ELOG("Error initializing: %s", error);
Sami Kyostila33668942018-11-13 16:33:32 +0000119 sqlite3_free(error);
120 }
Lalit Maganti17aa2732019-02-08 15:47:26 +0000121#endif
Sami Kyostila33668942018-11-13 16:33:32 +0000122}
123
Lalit Maganti086295b2019-04-04 16:59:19 +0100124void BuildBoundsTable(sqlite3* db, std::pair<int64_t, int64_t> bounds) {
125 char* error = nullptr;
126 sqlite3_exec(db, "DELETE FROM trace_bounds", nullptr, nullptr, &error);
127 if (error) {
128 PERFETTO_ELOG("Error deleting from bounds table: %s", error);
129 sqlite3_free(error);
130 return;
131 }
132
133 char* insert_sql = sqlite3_mprintf("INSERT INTO trace_bounds VALUES(%" PRId64
134 ", %" PRId64 ")",
135 bounds.first, bounds.second);
136
137 sqlite3_exec(db, insert_sql, 0, 0, &error);
138 sqlite3_free(insert_sql);
139 if (error) {
140 PERFETTO_ELOG("Error inserting bounds table: %s", error);
141 sqlite3_free(error);
142 }
143}
144
Sami Kyostila33668942018-11-13 16:33:32 +0000145void CreateBuiltinTables(sqlite3* db) {
146 char* error = nullptr;
147 sqlite3_exec(db, "CREATE TABLE perfetto_tables(name STRING)", 0, 0, &error);
148 if (error) {
149 PERFETTO_ELOG("Error initializing: %s", error);
150 sqlite3_free(error);
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000151 }
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000152 sqlite3_exec(db,
153 "CREATE TABLE trace_bounds(start_ts BIG INT, end_ts BIG INT)", 0,
154 0, &error);
155 if (error) {
156 PERFETTO_ELOG("Error initializing: %s", error);
157 sqlite3_free(error);
158 }
Rafal Slawikff8c9562020-09-09 15:46:35 +0100159 // Ensure that the entries in power_profile are unique to prevent duplicates
160 // when the power_profile is augmented with additional profiles.
Mikhail Khokhlov5686daf2020-06-09 16:50:45 +0100161 sqlite3_exec(db,
Rafal Slawikff8c9562020-09-09 15:46:35 +0100162 "CREATE TABLE power_profile("
163 "device STRING, cpu INT, cluster INT, freq INT, power DOUBLE,"
164 "UNIQUE(device, cpu, cluster, freq));",
Mikhail Khokhlov5686daf2020-06-09 16:50:45 +0100165 0, 0, &error);
166 if (error) {
167 PERFETTO_ELOG("Error initializing: %s", error);
168 sqlite3_free(error);
169 }
Deepanjan Roy18044c52020-09-02 17:45:15 -0400170 sqlite3_exec(db, "CREATE TABLE trace_metrics(name STRING)", 0, 0, &error);
171 if (error) {
172 PERFETTO_ELOG("Error initializing: %s", error);
173 sqlite3_free(error);
174 }
Deepanjan Royf6332e92020-09-21 11:08:42 -0400175 // This is a table intended to be used for metric debugging/developing. Data
176 // in the table is shown specially in the UI, and users can insert rows into
177 // this table to draw more things.
178 sqlite3_exec(db,
179 "CREATE TABLE debug_slices (id BIG INT, name STRING, ts BIG INT,"
180 "dur BIG INT, depth BIG INT)",
181 0, 0, &error);
182 if (error) {
183 PERFETTO_ELOG("Error initializing: %s", error);
184 sqlite3_free(error);
185 }
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000186
Lalit Maganti086295b2019-04-04 16:59:19 +0100187 // Initialize the bounds table with some data so even before parsing any data,
188 // we still have a valid table.
189 BuildBoundsTable(db, std::make_pair(0, 0));
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000190}
Hector Dearmanc0a29092018-11-08 17:34:23 +0000191
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000192void CreateBuiltinViews(sqlite3* db) {
193 char* error = nullptr;
194 sqlite3_exec(db,
Lalit Maganti809b2f92019-11-07 13:27:26 +0000195 "CREATE VIEW counter_definitions AS "
196 "SELECT "
197 " *, "
Lalit Magantibbc97002019-11-07 17:57:23 +0000198 " id AS counter_id "
Lalit Maganti809b2f92019-11-07 13:27:26 +0000199 "FROM counter_track",
200 0, 0, &error);
201 if (error) {
202 PERFETTO_ELOG("Error initializing: %s", error);
203 sqlite3_free(error);
204 }
205
206 sqlite3_exec(db,
Lalit Maganti69c94442019-11-07 18:59:02 +0000207 "CREATE VIEW counter_values AS "
208 "SELECT "
209 " *, "
210 " track_id as counter_id "
211 "FROM counter",
Lalit Magantibbc97002019-11-07 17:57:23 +0000212 0, 0, &error);
213 if (error) {
214 PERFETTO_ELOG("Error initializing: %s", error);
215 sqlite3_free(error);
216 }
217
218 sqlite3_exec(db,
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000219 "CREATE VIEW counters AS "
Lalit Maganti69c94442019-11-07 18:59:02 +0000220 "SELECT * "
Lalit Magantibbc97002019-11-07 17:57:23 +0000221 "FROM counter_values v "
222 "INNER JOIN counter_track t "
223 "ON v.track_id = t.id "
Lalit Maganti6fbb0ad2019-10-25 14:42:28 +0100224 "ORDER BY ts;",
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000225 0, 0, &error);
226 if (error) {
227 PERFETTO_ELOG("Error initializing: %s", error);
228 sqlite3_free(error);
229 }
Eric Seckler972225e2019-04-18 11:07:12 +0100230
231 sqlite3_exec(db,
232 "CREATE VIEW slice AS "
233 "SELECT "
234 " *, "
Lalit Magantibbc97002019-11-07 17:57:23 +0000235 " category AS cat, "
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000236 " id AS slice_id "
Eric Seckler972225e2019-04-18 11:07:12 +0100237 "FROM internal_slice;",
238 0, 0, &error);
239 if (error) {
240 PERFETTO_ELOG("Error initializing: %s", error);
241 sqlite3_free(error);
242 }
243
Lalit Maganti24b08332019-10-04 12:53:08 +0100244 sqlite3_exec(db,
Lalit Maganti80f566d2020-01-06 13:35:01 +0000245 "CREATE VIEW instants AS "
246 "SELECT "
247 "*, "
248 "0.0 as value "
249 "FROM instant;",
250 0, 0, &error);
Lalit Maganti1b620a62020-01-30 18:24:53 +0000251
252 if (error) {
253 PERFETTO_ELOG("Error initializing: %s", error);
254 sqlite3_free(error);
255 }
256
257 sqlite3_exec(db,
Lalit Magantia34007d2020-07-16 17:13:04 +0000258 "CREATE VIEW sched AS "
259 "SELECT "
260 "*, "
261 "ts + dur as ts_end "
262 "FROM sched_slice;",
Lalit Maganti1b620a62020-01-30 18:24:53 +0000263 0, 0, &error);
264
Lalit Maganti80f566d2020-01-06 13:35:01 +0000265 if (error) {
266 PERFETTO_ELOG("Error initializing: %s", error);
267 sqlite3_free(error);
268 }
269
Eric Seckler972225e2019-04-18 11:07:12 +0100270 // Legacy view for "slice" table with a deprecated table name.
271 // TODO(eseckler): Remove this view when all users have switched to "slice".
272 sqlite3_exec(db,
273 "CREATE VIEW slices AS "
274 "SELECT * FROM slice;",
275 0, 0, &error);
276 if (error) {
277 PERFETTO_ELOG("Error initializing: %s", error);
278 sqlite3_free(error);
279 }
Lalit Magantieac7fff2020-01-10 16:42:54 +0000280
281 sqlite3_exec(db,
282 "CREATE VIEW thread AS "
283 "SELECT "
284 "id as utid, "
285 "* "
286 "FROM internal_thread;",
287 0, 0, &error);
288 if (error) {
289 PERFETTO_ELOG("Error initializing: %s", error);
290 sqlite3_free(error);
291 }
292
293 sqlite3_exec(db,
294 "CREATE VIEW process AS "
295 "SELECT "
296 "id as upid, "
297 "* "
298 "FROM internal_process;",
299 0, 0, &error);
300 if (error) {
301 PERFETTO_ELOG("Error initializing: %s", error);
302 sqlite3_free(error);
303 }
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000304}
305
Lalit Maganti82517672021-11-04 23:39:15 +0000306struct ExportJson : public SqlFunction {
307 using Context = TraceStorage;
308 static base::Status Run(TraceStorage* storage,
309 size_t /*argc*/,
310 sqlite3_value** argv,
311 SqlValue& /*out*/,
312 Destructors&);
313};
314
315base::Status ExportJson::Run(TraceStorage* storage,
316 size_t /*argc*/,
317 sqlite3_value** argv,
318 SqlValue& /*out*/,
319 Destructors&) {
Eric Seckler37ad6af2019-10-08 15:51:14 +0100320 FILE* output;
321 if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
322 // Assume input is an FD.
323 output = fdopen(sqlite3_value_int(argv[0]), "w");
324 if (!output) {
Lalit Maganti82517672021-11-04 23:39:15 +0000325 return base::ErrStatus(
326 "EXPORT_JSON: Couldn't open output file from given FD");
Eric Seckler37ad6af2019-10-08 15:51:14 +0100327 }
328 } else {
329 const char* filename =
330 reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
331 output = fopen(filename, "w");
332 if (!output) {
Lalit Maganti82517672021-11-04 23:39:15 +0000333 return base::ErrStatus("EXPORT_JSON: Couldn't open output file");
Eric Seckler37ad6af2019-10-08 15:51:14 +0100334 }
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100335 }
Lalit Maganti82517672021-11-04 23:39:15 +0000336 return json::ExportJson(storage, output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100337}
338
Lalit Maganti82517672021-11-04 23:39:15 +0000339struct Hash : public SqlFunction {
340 static base::Status Run(void*,
341 size_t argc,
342 sqlite3_value** argv,
343 SqlValue& out,
344 Destructors&);
345};
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100346
Lalit Maganti82517672021-11-04 23:39:15 +0000347base::Status Hash::Run(void*,
348 size_t argc,
349 sqlite3_value** argv,
350 SqlValue& out,
351 Destructors&) {
Lalit Maganti062c8f82019-10-03 20:11:29 +0100352 base::Hash hash;
Lalit Maganti82517672021-11-04 23:39:15 +0000353 for (size_t i = 0; i < argc; ++i) {
Lalit Maganti062c8f82019-10-03 20:11:29 +0100354 sqlite3_value* value = argv[i];
Lalit Maganti82517672021-11-04 23:39:15 +0000355 int type = sqlite3_value_type(value);
356 switch (type) {
Lalit Maganti062c8f82019-10-03 20:11:29 +0100357 case SQLITE_INTEGER:
358 hash.Update(sqlite3_value_int64(value));
359 break;
360 case SQLITE_TEXT: {
361 const char* ptr =
362 reinterpret_cast<const char*>(sqlite3_value_text(value));
363 hash.Update(ptr, strlen(ptr));
364 break;
365 }
366 default:
Lalit Maganti82517672021-11-04 23:39:15 +0000367 return base::ErrStatus("HASH: arg %zu has unknown type %d", i, type);
Lalit Maganti062c8f82019-10-03 20:11:29 +0100368 }
369 }
Lalit Maganti82517672021-11-04 23:39:15 +0000370 out = SqlValue::Long(static_cast<int64_t>(hash.digest()));
371 return base::OkStatus();
Lalit Maganti062c8f82019-10-03 20:11:29 +0100372}
373
Lalit Maganti82517672021-11-04 23:39:15 +0000374struct Demangle : public SqlFunction {
375 static base::Status Run(void*,
376 size_t argc,
377 sqlite3_value** argv,
378 SqlValue& out,
379 Destructors& destructors);
380};
381
382base::Status Demangle::Run(void*,
383 size_t argc,
384 sqlite3_value** argv,
385 SqlValue& out,
386 Destructors& destructors) {
387 if (argc != 1)
388 return base::ErrStatus("Unsupported number of arg passed to DEMANGLE");
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000389 sqlite3_value* value = argv[0];
Lalit Maganti82517672021-11-04 23:39:15 +0000390 if (sqlite3_value_type(value) == SQLITE_NULL)
391 return base::OkStatus();
392
393 if (sqlite3_value_type(value) != SQLITE_TEXT)
394 return base::ErrStatus("Unsupported type of arg passed to DEMANGLE");
395
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000396 const char* ptr = reinterpret_cast<const char*>(sqlite3_value_text(value));
Primiano Tuccia1a26de2019-11-12 15:45:19 -0800397#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000398 int ignored = 0;
399 // This memory was allocated by malloc and will be passed to SQLite to free.
400 char* demangled_name = abi::__cxa_demangle(ptr, nullptr, nullptr, &ignored);
Lalit Maganti82517672021-11-04 23:39:15 +0000401 if (!demangled_name)
402 return base::OkStatus();
403
404 destructors.string_destructor = free;
405 out = SqlValue::String(demangled_name);
Primiano Tuccia1a26de2019-11-12 15:45:19 -0800406#else
Lalit Maganti82517672021-11-04 23:39:15 +0000407 destructors.string_destructor = sqlite_utils::kSqliteTransient;
408 out = SqlValue::String(ptr);
Primiano Tuccia1a26de2019-11-12 15:45:19 -0800409#endif
Lalit Maganti82517672021-11-04 23:39:15 +0000410 return base::OkStatus();
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000411}
412
Pascal Muetschard7e476092020-01-15 16:41:30 -0800413void LastNonNullStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
414 if (argc != 1) {
Lalit Maganti9bd8cd32020-03-24 16:00:05 +0000415 sqlite3_result_error(
416 ctx, "Unsupported number of args passed to LAST_NON_NULL", -1);
Pascal Muetschard7e476092020-01-15 16:41:30 -0800417 return;
418 }
419 sqlite3_value* value = argv[0];
420 if (sqlite3_value_type(value) == SQLITE_NULL) {
421 return;
422 }
423 sqlite3_value** ptr = reinterpret_cast<sqlite3_value**>(
424 sqlite3_aggregate_context(ctx, sizeof(sqlite3_value*)));
425 if (ptr) {
426 if (*ptr != nullptr) {
427 sqlite3_value_free(*ptr);
428 }
429 *ptr = sqlite3_value_dup(value);
430 }
431}
432
433void LastNonNullInverse(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
434 // Do nothing.
435 base::ignore_result(ctx);
436 base::ignore_result(argc);
437 base::ignore_result(argv);
438}
439
440void LastNonNullValue(sqlite3_context* ctx) {
441 sqlite3_value** ptr =
442 reinterpret_cast<sqlite3_value**>(sqlite3_aggregate_context(ctx, 0));
443 if (!ptr || !*ptr) {
444 sqlite3_result_null(ctx);
445 } else {
446 sqlite3_result_value(ctx, *ptr);
447 }
448}
449
450void LastNonNullFinal(sqlite3_context* ctx) {
451 sqlite3_value** ptr =
452 reinterpret_cast<sqlite3_value**>(sqlite3_aggregate_context(ctx, 0));
453 if (!ptr || !*ptr) {
454 sqlite3_result_null(ctx);
455 } else {
456 sqlite3_result_value(ctx, *ptr);
457 sqlite3_value_free(*ptr);
458 }
459}
460
Lalit Maganti82517672021-11-04 23:39:15 +0000461void RegisterLastNonNullFunction(sqlite3* db) {
Pascal Muetschard7e476092020-01-15 16:41:30 -0800462 auto ret = sqlite3_create_window_function(
463 db, "LAST_NON_NULL", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr,
464 &LastNonNullStep, &LastNonNullFinal, &LastNonNullValue,
465 &LastNonNullInverse, nullptr);
466 if (ret) {
467 PERFETTO_ELOG("Error initializing LAST_NON_NULL");
468 }
469}
470
Lalit Maganti6b72d172020-07-22 13:29:24 +0100471struct ValueAtMaxTsContext {
Lalit Maganti664e9f32020-07-24 16:13:34 +0100472 bool initialized;
473 int value_type;
474
Lalit Maganti6b72d172020-07-22 13:29:24 +0100475 int64_t max_ts;
Lalit Maganti664e9f32020-07-24 16:13:34 +0100476 int64_t int_value_at_max_ts;
477 double double_value_at_max_ts;
Lalit Maganti6b72d172020-07-22 13:29:24 +0100478};
479
480void ValueAtMaxTsStep(sqlite3_context* ctx, int, sqlite3_value** argv) {
481 sqlite3_value* ts = argv[0];
482 sqlite3_value* value = argv[1];
483
Lalit Maganti664e9f32020-07-24 16:13:34 +0100484 // Note that sqlite3_aggregate_context zeros the memory for us so all the
485 // variables of the struct should be zero.
486 ValueAtMaxTsContext* fn_ctx = reinterpret_cast<ValueAtMaxTsContext*>(
487 sqlite3_aggregate_context(ctx, sizeof(ValueAtMaxTsContext)));
488
489 // For performance reasons, we only do the check for the type of ts and value
490 // on the first call of the function.
491 if (PERFETTO_UNLIKELY(!fn_ctx->initialized)) {
492 if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
493 sqlite3_result_error(ctx, "VALUE_AT_MAX_TS: ts passed was not an integer",
494 -1);
495 return;
496 }
497
498 fn_ctx->value_type = sqlite3_value_type(value);
499 if (fn_ctx->value_type != SQLITE_INTEGER &&
500 fn_ctx->value_type != SQLITE_FLOAT) {
501 sqlite3_result_error(
502 ctx, "VALUE_AT_MAX_TS: value passed was not an integer or float", -1);
503 return;
504 }
505
506 fn_ctx->initialized = true;
507 }
508
509 // On dcheck builds however, we check every passed ts and value.
Lalit Maganti6b72d172020-07-22 13:29:24 +0100510#if PERFETTO_DCHECK_IS_ON()
511 if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
512 sqlite3_result_error(ctx, "VALUE_AT_MAX_TS: ts passed was not an integer",
513 -1);
514 return;
515 }
Lalit Maganti664e9f32020-07-24 16:13:34 +0100516 if (sqlite3_value_type(value) != fn_ctx->value_type) {
517 sqlite3_result_error(ctx, "VALUE_AT_MAX_TS: value type is inconsistent",
518 -1);
Lalit Maganti6b72d172020-07-22 13:29:24 +0100519 return;
520 }
521#endif
522
Lalit Maganti6b72d172020-07-22 13:29:24 +0100523 int64_t ts_int = sqlite3_value_int64(ts);
Lalit Maganti664e9f32020-07-24 16:13:34 +0100524 if (PERFETTO_LIKELY(fn_ctx->max_ts < ts_int)) {
Lalit Maganti6b72d172020-07-22 13:29:24 +0100525 fn_ctx->max_ts = ts_int;
Lalit Maganti664e9f32020-07-24 16:13:34 +0100526
527 if (fn_ctx->value_type == SQLITE_INTEGER) {
528 fn_ctx->int_value_at_max_ts = sqlite3_value_int64(value);
529 } else {
530 fn_ctx->double_value_at_max_ts = sqlite3_value_double(value);
531 }
Lalit Maganti6b72d172020-07-22 13:29:24 +0100532 }
533}
534
535void ValueAtMaxTsFinal(sqlite3_context* ctx) {
536 ValueAtMaxTsContext* fn_ctx =
537 reinterpret_cast<ValueAtMaxTsContext*>(sqlite3_aggregate_context(ctx, 0));
538 if (!fn_ctx) {
539 sqlite3_result_null(ctx);
540 return;
541 }
Lalit Maganti664e9f32020-07-24 16:13:34 +0100542 if (fn_ctx->value_type == SQLITE_INTEGER) {
543 sqlite3_result_int64(ctx, fn_ctx->int_value_at_max_ts);
544 } else {
545 sqlite3_result_double(ctx, fn_ctx->double_value_at_max_ts);
546 }
Lalit Maganti6b72d172020-07-22 13:29:24 +0100547}
548
Lalit Maganti82517672021-11-04 23:39:15 +0000549void RegisterValueAtMaxTsFunction(sqlite3* db) {
Lalit Maganti6b72d172020-07-22 13:29:24 +0100550 auto ret = sqlite3_create_function_v2(
551 db, "VALUE_AT_MAX_TS", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr,
552 nullptr, &ValueAtMaxTsStep, &ValueAtMaxTsFinal, nullptr);
553 if (ret) {
554 PERFETTO_ELOG("Error initializing VALUE_AT_MAX_TS");
555 }
556}
557
Lalit Maganti82517672021-11-04 23:39:15 +0000558struct ExtractArg : public SqlFunction {
559 using Context = TraceStorage;
560 static base::Status Run(TraceStorage* storage,
561 size_t argc,
562 sqlite3_value** argv,
563 SqlValue& out,
564 Destructors& destructors);
565};
566
567base::Status ExtractArg::Run(TraceStorage* storage,
568 size_t argc,
569 sqlite3_value** argv,
570 SqlValue& out,
571 Destructors& destructors) {
572 if (argc != 2)
573 return base::ErrStatus("EXTRACT_ARG: 2 args required");
Lalit Magantib6fe0272021-03-18 14:37:07 +0000574
575 // If the arg set id is null, just return null as the result.
Lalit Maganti82517672021-11-04 23:39:15 +0000576 if (sqlite3_value_type(argv[0]) == SQLITE_NULL)
577 return base::OkStatus();
Lalit Maganti94369c02020-04-15 16:21:37 +0100578
Lalit Maganti82517672021-11-04 23:39:15 +0000579 if (sqlite3_value_type(argv[0]) != SQLITE_INTEGER)
580 return base::ErrStatus("EXTRACT_ARG: 1st argument should be arg set id");
581
582 if (sqlite3_value_type(argv[1]) != SQLITE_TEXT)
583 return base::ErrStatus("EXTRACT_ARG: 2nd argument should be key");
584
Lalit Maganti94369c02020-04-15 16:21:37 +0100585 uint32_t arg_set_id = static_cast<uint32_t>(sqlite3_value_int(argv[0]));
586 const char* key = reinterpret_cast<const char*>(sqlite3_value_text(argv[1]));
587
Lalit Maganti3e68e202020-08-19 12:29:56 +0100588 base::Optional<Variadic> opt_value;
Lalit Maganti82517672021-11-04 23:39:15 +0000589 RETURN_IF_ERROR(storage->ExtractArg(arg_set_id, key, &opt_value));
Lalit Maganti3e68e202020-08-19 12:29:56 +0100590
Lalit Maganti82517672021-11-04 23:39:15 +0000591 if (!opt_value)
592 return base::OkStatus();
593
594 // This function always returns static strings (i.e. scoped to lifetime
595 // of the TraceStorage thread pool) so prevent SQLite from making copies.
596 destructors.string_destructor = sqlite_utils::kSqliteStatic;
Lalit Maganti94369c02020-04-15 16:21:37 +0100597
Lalit Maganti3e68e202020-08-19 12:29:56 +0100598 switch (opt_value->type) {
Alexander Timin76778252021-10-04 13:24:46 +0000599 case Variadic::kNull:
Lalit Maganti82517672021-11-04 23:39:15 +0000600 return base::OkStatus();
601 case Variadic::kInt:
602 out = SqlValue::Long(opt_value->int_value);
603 return base::OkStatus();
604 case Variadic::kUint:
605 out = SqlValue::Long(static_cast<int64_t>(opt_value->uint_value));
606 return base::OkStatus();
607 case Variadic::kString:
608 out =
609 SqlValue::String(storage->GetString(opt_value->string_value).data());
610 return base::OkStatus();
611 case Variadic::kReal:
612 out = SqlValue::Double(opt_value->real_value);
613 return base::OkStatus();
614 case Variadic::kBool:
615 out = SqlValue::Long(opt_value->bool_value);
616 return base::OkStatus();
617 case Variadic::kPointer:
618 out = SqlValue::Long(static_cast<int64_t>(opt_value->pointer_value));
619 return base::OkStatus();
620 case Variadic::kJson:
621 out = SqlValue::String(storage->GetString(opt_value->json_value).data());
622 return base::OkStatus();
Lalit Maganti94369c02020-04-15 16:21:37 +0100623 }
Lalit Maganti82517672021-11-04 23:39:15 +0000624 PERFETTO_FATAL("For GCC");
Lalit Magantic5bd7462021-07-01 20:40:55 +0100625}
626
Deepanjan Roy4ed736c2021-08-12 20:54:02 -0400627std::vector<std::string> SanitizeMetricMountPaths(
628 const std::vector<std::string>& mount_paths) {
629 std::vector<std::string> sanitized;
630 for (const auto& path : mount_paths) {
631 if (path.length() == 0)
632 continue;
633 sanitized.push_back(path);
634 if (path.back() != '/')
635 sanitized.back().append("/");
636 }
637 return sanitized;
638}
639
Lalit Maganti82517672021-11-04 23:39:15 +0000640struct SourceGeq : public SqlFunction {
641 static base::Status Run(void*,
642 size_t,
643 sqlite3_value**,
644 SqlValue&,
645 Destructors&) {
646 return base::ErrStatus(
647 "SOURCE_GEQ should not be called from the global scope");
648 }
649};
650
Lalit Maganti2553b802019-05-24 13:25:58 +0100651void SetupMetrics(TraceProcessor* tp,
652 sqlite3* db,
Deepanjan Roy4ed736c2021-08-12 20:54:02 -0400653 std::vector<metrics::SqlMetricFile>* sql_metrics,
654 const std::vector<std::string>& extension_paths) {
655 const std::vector<std::string> sanitized_extension_paths =
656 SanitizeMetricMountPaths(extension_paths);
657 std::vector<std::string> skip_prefixes;
Hector Dearmand865c372021-08-23 11:50:10 +0100658 skip_prefixes.reserve(sanitized_extension_paths.size());
Deepanjan Roy4ed736c2021-08-12 20:54:02 -0400659 for (const auto& path : sanitized_extension_paths) {
660 skip_prefixes.push_back(kMetricProtoRoot + path);
661 }
662 tp->ExtendMetricsProto(kMetricsDescriptor.data(), kMetricsDescriptor.size(),
663 skip_prefixes);
Deepanjan Royf4da5092020-07-15 17:59:04 -0400664 tp->ExtendMetricsProto(kAllChromeMetricsDescriptor.data(),
Deepanjan Roy4ed736c2021-08-12 20:54:02 -0400665 kAllChromeMetricsDescriptor.size(), skip_prefixes);
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100666
Lalit Maganti2553b802019-05-24 13:25:58 +0100667 for (const auto& file_to_sql : metrics::sql_metrics::kFileToSql) {
Deepanjan Roy4ed736c2021-08-12 20:54:02 -0400668 if (base::StartsWithAny(file_to_sql.path, sanitized_extension_paths))
669 continue;
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100670 tp->RegisterMetric(file_to_sql.path, file_to_sql.sql);
Lalit Maganti2553b802019-05-24 13:25:58 +0100671 }
672
Lalit Maganti82517672021-11-04 23:39:15 +0000673 RegisterFunction<metrics::NullIfEmpty>(db, "NULL_IF_EMPTY", 1);
674 RegisterFunction<metrics::UnwrapMetricProto>(db, "UNWRAP_METRIC_PROTO", 2);
675 RegisterFunction<metrics::RunMetric>(
676 db, "RUN_METRIC", -1,
677 std::unique_ptr<metrics::RunMetric::Context>(
678 new metrics::RunMetric::Context{tp, sql_metrics}));
Lalit Maganti2553b802019-05-24 13:25:58 +0100679
Lalit Maganti82517672021-11-04 23:39:15 +0000680 // TODO(lalitm): migrate this over to using RegisterFunction once aggregate
681 // functions are supported.
Lalit Maganti2553b802019-05-24 13:25:58 +0100682 {
683 auto ret = sqlite3_create_function_v2(
684 db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr,
685 metrics::RepeatedFieldStep, metrics::RepeatedFieldFinal, nullptr);
686 if (ret)
Lalit Maganti9bc389a2020-07-02 16:57:00 +0100687 PERFETTO_FATAL("Error initializing RepeatedField");
688 }
Lalit Maganti2553b802019-05-24 13:25:58 +0100689}
Oystein Eftevaag477bbff2020-01-27 11:07:49 -0800690
691void EnsureSqliteInitialized() {
692 // sqlite3_initialize isn't actually thread-safe despite being documented
693 // as such; we need to make sure multiple TraceProcessorImpl instances don't
694 // call it concurrently and only gets called once per process, instead.
Lalit Maganti1e5630e2020-01-29 12:34:14 +0000695 static bool init_once = [] { return sqlite3_initialize() == SQLITE_OK; }();
Oystein Eftevaag477bbff2020-01-27 11:07:49 -0800696 PERFETTO_CHECK(init_once);
697}
698
Deepanjan Roy18044c52020-09-02 17:45:15 -0400699void InsertIntoTraceMetricsTable(sqlite3* db, const std::string& metric_name) {
700 char* insert_sql = sqlite3_mprintf(
701 "INSERT INTO trace_metrics(name) VALUES('%q')", metric_name.c_str());
702 char* insert_error = nullptr;
703 sqlite3_exec(db, insert_sql, nullptr, nullptr, &insert_error);
704 sqlite3_free(insert_sql);
705 if (insert_error) {
706 PERFETTO_ELOG("Error registering table: %s", insert_error);
707 sqlite3_free(insert_error);
708 }
709}
710
Hector Dearmanc0a29092018-11-08 17:34:23 +0000711} // namespace
712
Eric Secklera7870e62019-11-01 10:11:58 +0000713TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
714 : TraceProcessorStorageImpl(cfg) {
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000715 context_.fuchsia_trace_tokenizer.reset(new FuchsiaTraceTokenizer(&context_));
716 context_.fuchsia_trace_parser.reset(new FuchsiaTraceParser(&context_));
717
718 context_.systrace_trace_parser.reset(new SystraceTraceParser(&context_));
719
Lalit Maganti69216ec2021-05-21 14:10:42 +0100720 if (util::IsGzipSupported())
Lalit Maganti9d538bd2020-03-12 23:48:16 +0000721 context_.gzip_trace_parser.reset(new GzipTraceParser(&context_));
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000722
Lalit Maganti0bfeb972020-03-14 03:57:30 +0000723 if (json::IsJsonSupported()) {
724 context_.json_trace_tokenizer.reset(new JsonTraceTokenizer(&context_));
725 context_.json_trace_parser.reset(new JsonTraceParser(&context_));
726 }
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000727
Mikhail Khokhlov692087e2019-12-11 10:53:45 +0000728 RegisterAdditionalModules(&context_);
Lalit Maganti6d1f7b52020-02-27 13:16:44 +0000729
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000730 sqlite3* db = nullptr;
Oystein Eftevaag477bbff2020-01-27 11:07:49 -0800731 EnsureSqliteInitialized();
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000732 PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
Ioannis Ilkos7199d552019-03-13 18:35:31 +0000733 InitializeSqlite(db);
Sami Kyostila33668942018-11-13 16:33:32 +0000734 CreateBuiltinTables(db);
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000735 CreateBuiltinViews(db);
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000736 db_.reset(std::move(db));
737
Lalit Maganti82517672021-11-04 23:39:15 +0000738 // New style function registration.
739 RegisterFunction<Hash>(db, "HASH", -1);
740 RegisterFunction<Demangle>(db, "DEMANGLE", 1);
741 RegisterFunction<SourceGeq>(db, "SOURCE_GEQ", -1);
742 RegisterFunction<ExportJson>(db, "EXPORT_JSON", 1, context_.storage.get(),
743 false);
744 RegisterFunction<ExtractArg>(db, "EXTRACT_ARG", 2, context_.storage.get());
745
746 // Old style function registration.
747 // TODO(lalitm): migrate this over to using RegisterFunction once aggregate
748 // functions are supported.
749 RegisterLastNonNullFunction(db);
750 RegisterValueAtMaxTsFunction(db);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100751
Deepanjan Roy4ed736c2021-08-12 20:54:02 -0400752 SetupMetrics(this, *db_, &sql_metrics_, cfg.skip_builtin_metric_paths);
Lalit Maganti2553b802019-05-24 13:25:58 +0100753
Lalit Maganti65800eb2020-01-30 15:18:59 +0000754 // Setup the query cache.
755 query_cache_.reset(new QueryCache());
756
Lalit Maganti786cc922019-09-06 16:04:32 +0100757 const TraceStorage* storage = context_.storage.get();
Lalit Maganti809b2f92019-11-07 13:27:26 +0000758
Lalit Maganti679b29d2020-01-13 13:26:28 +0000759 SqlStatsTable::RegisterTable(*db_, storage);
Lalit Maganti679b29d2020-01-13 13:26:28 +0000760 StatsTable::RegisterTable(*db_, storage);
761
Lalit Maganti8a39fae2020-01-20 17:22:10 +0000762 // Operator tables.
763 SpanJoinOperatorTable::RegisterTable(*db_, storage);
764 WindowOperatorTable::RegisterTable(*db_, storage);
765
Lalit Maganti679b29d2020-01-13 13:26:28 +0000766 // New style tables but with some custom logic.
Isabelle Taylore908fe82020-06-01 01:52:17 +0100767 SqliteRawTable::RegisterTable(*db_, query_cache_.get(), &context_);
Lalit Maganti920f4f92020-02-19 13:45:05 +0000768
769 // Tables dynamically generated at query time.
770 RegisterDynamicTable(std::unique_ptr<ExperimentalFlamegraphGenerator>(
771 new ExperimentalFlamegraphGenerator(&context_)));
772 RegisterDynamicTable(std::unique_ptr<ExperimentalCounterDurGenerator>(
773 new ExperimentalCounterDurGenerator(storage->counter_table())));
Lalit Maganti97d7d472020-04-07 18:49:17 +0100774 RegisterDynamicTable(std::unique_ptr<DescribeSliceGenerator>(
775 new DescribeSliceGenerator(&context_)));
Hector Dearman5b523762020-04-16 10:36:32 +0100776 RegisterDynamicTable(std::unique_ptr<ExperimentalSliceLayoutGenerator>(
777 new ExperimentalSliceLayoutGenerator(
778 context_.storage.get()->mutable_string_pool(),
779 &storage->slice_table())));
Stephen Nuskodd7f6dc2020-11-26 17:04:08 -0500780 RegisterDynamicTable(std::unique_ptr<AncestorGenerator>(
781 new AncestorGenerator(AncestorGenerator::Ancestor::kSlice, &context_)));
782 RegisterDynamicTable(std::unique_ptr<AncestorGenerator>(new AncestorGenerator(
783 AncestorGenerator::Ancestor::kStackProfileCallsite, &context_)));
Zaina Al-Mashni3af1fae2021-09-09 09:08:11 +0000784 RegisterDynamicTable(std::unique_ptr<AncestorGenerator>(new AncestorGenerator(
785 AncestorGenerator::Ancestor::kSliceByStack, &context_)));
Zaina Al-Mashni5ed83f92021-09-09 09:08:38 +0000786 RegisterDynamicTable(
787 std::unique_ptr<DescendantGenerator>(new DescendantGenerator(
788 DescendantGenerator::Descendant::kSlice, &context_)));
789 RegisterDynamicTable(
790 std::unique_ptr<DescendantGenerator>(new DescendantGenerator(
791 DescendantGenerator::Descendant::kSliceByStack, &context_)));
Andrii824107d2020-09-29 10:13:36 +0300792 RegisterDynamicTable(
793 std::unique_ptr<ConnectedFlowGenerator>(new ConnectedFlowGenerator(
ssid44f123f2021-01-08 16:04:41 -0800794 ConnectedFlowGenerator::Mode::kDirectlyConnectedFlow, &context_)));
Andrii824107d2020-09-29 10:13:36 +0300795 RegisterDynamicTable(
796 std::unique_ptr<ConnectedFlowGenerator>(new ConnectedFlowGenerator(
ssid44f123f2021-01-08 16:04:41 -0800797 ConnectedFlowGenerator::Mode::kPrecedingFlow, &context_)));
Andrii824107d2020-09-29 10:13:36 +0300798 RegisterDynamicTable(
799 std::unique_ptr<ConnectedFlowGenerator>(new ConnectedFlowGenerator(
ssid44f123f2021-01-08 16:04:41 -0800800 ConnectedFlowGenerator::Mode::kFollowingFlow, &context_)));
Lalit Magantic59b1bc2020-07-28 16:36:58 +0100801 RegisterDynamicTable(std::unique_ptr<ExperimentalSchedUpidGenerator>(
802 new ExperimentalSchedUpidGenerator(storage->sched_slice_table(),
803 storage->thread_table())));
Lalit Maganti2fc5db22020-08-13 15:02:47 +0100804 RegisterDynamicTable(std::unique_ptr<ThreadStateGenerator>(
805 new ThreadStateGenerator(&context_)));
Ryanddeb3b12021-04-12 15:55:17 +0100806 RegisterDynamicTable(std::unique_ptr<ExperimentalAnnotatedStackGenerator>(
807 new ExperimentalAnnotatedStackGenerator(&context_)));
Lalit Maganti40fbe8e2021-06-10 16:21:25 +0100808 RegisterDynamicTable(std::unique_ptr<ExperimentalFlatSliceGenerator>(
809 new ExperimentalFlatSliceGenerator(&context_)));
Lalit Maganti679b29d2020-01-13 13:26:28 +0000810
811 // New style db-backed tables.
Lalit Maganti65800eb2020-01-30 15:18:59 +0000812 RegisterDbTable(storage->arg_table());
813 RegisterDbTable(storage->thread_table());
814 RegisterDbTable(storage->process_table());
Lalit Maganti1908e262020-01-09 14:33:19 +0000815
Lalit Maganti65800eb2020-01-30 15:18:59 +0000816 RegisterDbTable(storage->slice_table());
AndrewB330c879ea42020-07-29 14:12:39 +0300817 RegisterDbTable(storage->flow_table());
Stephen Nuskof848d462021-04-06 13:28:04 +0100818 RegisterDbTable(storage->thread_slice_table());
Lalit Maganti1b620a62020-01-30 18:24:53 +0000819 RegisterDbTable(storage->sched_slice_table());
Lalit Maganti65800eb2020-01-30 15:18:59 +0000820 RegisterDbTable(storage->instant_table());
821 RegisterDbTable(storage->gpu_slice_table());
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000822
Lalit Maganti65800eb2020-01-30 15:18:59 +0000823 RegisterDbTable(storage->track_table());
824 RegisterDbTable(storage->thread_track_table());
825 RegisterDbTable(storage->process_track_table());
826 RegisterDbTable(storage->gpu_track_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000827
Lalit Maganti65800eb2020-01-30 15:18:59 +0000828 RegisterDbTable(storage->counter_table());
Lalit Maganti4b3b3ad2019-12-04 19:27:35 +0000829
Lalit Maganti65800eb2020-01-30 15:18:59 +0000830 RegisterDbTable(storage->counter_track_table());
831 RegisterDbTable(storage->process_counter_track_table());
832 RegisterDbTable(storage->thread_counter_track_table());
833 RegisterDbTable(storage->cpu_counter_track_table());
834 RegisterDbTable(storage->irq_counter_track_table());
835 RegisterDbTable(storage->softirq_counter_track_table());
836 RegisterDbTable(storage->gpu_counter_track_table());
Raymond Chiu324f9952020-03-26 10:23:19 -0700837 RegisterDbTable(storage->gpu_counter_group_table());
Ryan Savitskic6c7e842021-03-10 14:26:59 +0000838 RegisterDbTable(storage->perf_counter_track_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000839
Lalit Maganti65800eb2020-01-30 15:18:59 +0000840 RegisterDbTable(storage->heap_graph_object_table());
841 RegisterDbTable(storage->heap_graph_reference_table());
Florian Mayer22588ad2020-04-08 16:14:34 +0200842 RegisterDbTable(storage->heap_graph_class_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000843
Lalit Maganti65800eb2020-01-30 15:18:59 +0000844 RegisterDbTable(storage->symbol_table());
845 RegisterDbTable(storage->heap_profile_allocation_table());
846 RegisterDbTable(storage->cpu_profile_stack_sample_table());
Ryan Savitskif00cad32020-07-03 17:14:27 +0100847 RegisterDbTable(storage->perf_sample_table());
Lalit Maganti65800eb2020-01-30 15:18:59 +0000848 RegisterDbTable(storage->stack_profile_callsite_table());
849 RegisterDbTable(storage->stack_profile_mapping_table());
850 RegisterDbTable(storage->stack_profile_frame_table());
Florian Mayer19ce3952020-04-08 15:27:32 +0200851 RegisterDbTable(storage->package_list_table());
Florian Mayer2f12d432020-04-09 14:42:46 +0200852 RegisterDbTable(storage->profiler_smaps_table());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000853
Lalit Maganti65800eb2020-01-30 15:18:59 +0000854 RegisterDbTable(storage->android_log_table());
Lalit Magantif1ab24f2020-01-07 17:42:26 +0000855
Lalit Maganti65800eb2020-01-30 15:18:59 +0000856 RegisterDbTable(storage->vulkan_memory_allocations_table());
Lalit Magantiededb0e2020-01-08 12:50:34 +0000857
Adithya Srinivasan4d9bf422020-03-24 13:33:16 -0700858 RegisterDbTable(storage->graphics_frame_slice_table());
Adithya Srinivasan4d9bf422020-03-24 13:33:16 -0700859
Adithya Srinivasan526a34e2020-11-06 13:40:58 -0800860 RegisterDbTable(storage->expected_frame_timeline_slice_table());
861 RegisterDbTable(storage->actual_frame_timeline_slice_table());
862
Lalit Maganti65800eb2020-01-30 15:18:59 +0000863 RegisterDbTable(storage->metadata_table());
Rafal Slawik361df132020-05-21 16:55:23 +0100864 RegisterDbTable(storage->cpu_table());
865 RegisterDbTable(storage->cpu_freq_table());
Lalit Maganti710fbbb2021-05-14 17:48:01 +0100866 RegisterDbTable(storage->clock_snapshot_table());
Witold Fijalkowskicdaed0e2020-10-02 09:47:21 +0200867
868 RegisterDbTable(storage->memory_snapshot_table());
869 RegisterDbTable(storage->process_memory_snapshot_table());
870 RegisterDbTable(storage->memory_snapshot_node_table());
871 RegisterDbTable(storage->memory_snapshot_edge_table());
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000872}
873
Lalit Magantib834f8c2020-06-17 11:43:17 +0100874TraceProcessorImpl::~TraceProcessorImpl() = default;
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000875
Primiano Tucci3264b592021-11-08 18:20:51 +0000876util::Status TraceProcessorImpl::Parse(TraceBlobView blob) {
877 bytes_parsed_ += blob.size();
878 return TraceProcessorStorageImpl::Parse(std::move(blob));
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000879}
880
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100881std::string TraceProcessorImpl::GetCurrentTraceName() {
882 if (current_trace_name_.empty())
883 return "";
884 auto size = " (" + std::to_string(bytes_parsed_ / 1024 / 1024) + " MB)";
885 return current_trace_name_ + size;
886}
887
888void TraceProcessorImpl::SetCurrentTraceName(const std::string& name) {
889 current_trace_name_ = name;
890}
891
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000892void TraceProcessorImpl::NotifyEndOfFile() {
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100893 if (current_trace_name_.empty())
894 current_trace_name_ = "Unnamed trace";
895
Eric Secklera7870e62019-11-01 10:11:58 +0000896 TraceProcessorStorageImpl::NotifyEndOfFile();
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700897
Mikhail Khokhlov81491b92019-12-19 13:58:22 +0000898 SchedEventTracker::GetOrCreate(&context_)->FlushPendingEvents();
Hector Dearman93b0b092020-01-09 14:35:04 +0000899 context_.metadata_tracker->SetMetadata(
900 metadata::trace_size_bytes,
901 Variadic::Integer(static_cast<int64_t>(bytes_parsed_)));
Hector Dearman7dbfa1c2021-01-15 14:01:26 +0000902 BuildBoundsTable(*db_, context_.storage->GetTraceTimestampBoundsNs());
Primiano Tucci11a79e72019-10-29 22:13:10 +0100903
904 // Create a snapshot of all tables and views created so far. This is so later
905 // we can drop all extra tables created by the UI and reset to the original
906 // state (see RestoreInitialTables).
907 initial_tables_.clear();
908 auto it = ExecuteQuery(kAllTablesQuery);
909 while (it.Next()) {
910 auto value = it.Get(0);
911 PERFETTO_CHECK(value.type == SqlValue::Type::kString);
912 initial_tables_.push_back(value.string_value);
913 }
914}
915
916size_t TraceProcessorImpl::RestoreInitialTables() {
Lalit Maganti97b08e12021-05-17 13:35:31 +0100917 // Step 1: figure out what tables/views/indices we need to delete.
Primiano Tucci11a79e72019-10-29 22:13:10 +0100918 std::vector<std::pair<std::string, std::string>> deletion_list;
919 std::string msg = "Resetting DB to initial state, deleting table/views:";
920 for (auto it = ExecuteQuery(kAllTablesQuery); it.Next();) {
921 std::string name(it.Get(0).string_value);
922 std::string type(it.Get(1).string_value);
923 if (std::find(initial_tables_.begin(), initial_tables_.end(), name) ==
924 initial_tables_.end()) {
925 msg += " " + name;
926 deletion_list.push_back(std::make_pair(type, name));
927 }
928 }
929
930 PERFETTO_LOG("%s", msg.c_str());
Lalit Maganti97b08e12021-05-17 13:35:31 +0100931
932 // Step 2: actually delete those tables/views/indices.
Primiano Tucci11a79e72019-10-29 22:13:10 +0100933 for (const auto& tn : deletion_list) {
934 std::string query = "DROP " + tn.first + " " + tn.second;
935 auto it = ExecuteQuery(query);
936 while (it.Next()) {
937 }
Primiano Tucci1b4c8fc2020-01-15 22:29:42 +0000938 // Index deletion can legitimately fail. If one creates an index "i" on a
939 // table "t" but issues the deletion in the order (t, i), the DROP index i
940 // will fail with "no such index" because deleting the table "t"
941 // automatically deletes all associated indexes.
942 if (!it.Status().ok() && tn.first != "index")
943 PERFETTO_FATAL("%s -> %s", query.c_str(), it.Status().c_message());
Primiano Tucci11a79e72019-10-29 22:13:10 +0100944 }
945 return deletion_list.size();
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000946}
947
Primiano Tucci4e01f632020-06-11 17:03:05 +0100948Iterator TraceProcessorImpl::ExecuteQuery(const std::string& sql,
949 int64_t time_queued) {
Lalit Maganti77095012019-02-19 13:13:59 +0000950 sqlite3_stmt* raw_stmt;
Lalit Maganti427b8332020-05-27 16:09:45 +0100951 int err;
952 {
953 PERFETTO_TP_TRACE("QUERY_PREPARE");
954 err = sqlite3_prepare_v2(*db_, sql.c_str(), static_cast<int>(sql.size()),
955 &raw_stmt, nullptr);
956 }
957
Lalit Maganti1f067182019-05-09 14:50:05 +0100958 util::Status status;
Lalit Maganti06acc022019-04-03 16:02:15 +0100959 uint32_t col_count = 0;
960 if (err != SQLITE_OK) {
Lalit Maganti7ee6abb2019-05-09 17:57:32 +0100961 status = util::ErrStatus("%s", sqlite3_errmsg(*db_));
Lalit Maganti77095012019-02-19 13:13:59 +0000962 } else {
963 col_count = static_cast<uint32_t>(sqlite3_column_count(raw_stmt));
964 }
Lalit Magantiaac2f652019-04-30 12:16:21 +0100965
966 base::TimeNanos t_start = base::GetWallTimeNs();
967 uint32_t sql_stats_row =
968 context_.storage->mutable_sql_stats()->RecordQueryBegin(sql, time_queued,
969 t_start.count());
970
971 std::unique_ptr<IteratorImpl> impl(new IteratorImpl(
Lalit Maganti1f067182019-05-09 14:50:05 +0100972 this, *db_, ScopedStmt(raw_stmt), col_count, status, sql_stats_row));
Primiano Tucci4e01f632020-06-11 17:03:05 +0100973 return Iterator(std::move(impl));
Lalit Maganti77095012019-02-19 13:13:59 +0000974}
975
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000976void TraceProcessorImpl::InterruptQuery() {
977 if (!db_)
978 return;
979 query_interrupted_.store(true);
980 sqlite3_interrupt(db_.get());
981}
982
Deepanjan Roy18044c52020-09-02 17:45:15 -0400983bool TraceProcessorImpl::IsRootMetricField(const std::string& metric_name) {
984 base::Optional<uint32_t> desc_idx =
985 pool_.FindDescriptorIdx(".perfetto.protos.TraceMetrics");
986 if (!desc_idx.has_value())
987 return false;
Andrew Shulaevba0a5d12021-01-07 08:44:50 +0000988 auto field_idx = pool_.descriptors()[*desc_idx].FindFieldByName(metric_name);
989 return field_idx != nullptr;
Deepanjan Roy18044c52020-09-02 17:45:15 -0400990}
991
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100992util::Status TraceProcessorImpl::RegisterMetric(const std::string& path,
993 const std::string& sql) {
Lalit Magantif9d80302019-06-19 12:48:25 +0100994 std::string stripped_sql;
995 for (base::StringSplitter sp(sql, '\n'); sp.Next();) {
996 if (strncmp(sp.cur_token(), "--", 2) != 0) {
997 stripped_sql.append(sp.cur_token());
998 stripped_sql.push_back('\n');
999 }
1000 }
1001
1002 // Check if the metric with the given path already exists and if it does, just
1003 // update the SQL associated with it.
1004 auto it = std::find_if(
1005 sql_metrics_.begin(), sql_metrics_.end(),
1006 [&path](const metrics::SqlMetricFile& m) { return m.path == path; });
1007 if (it != sql_metrics_.end()) {
1008 it->sql = stripped_sql;
1009 return util::OkStatus();
1010 }
1011
Hector Dearman9f5b5bf2021-01-29 14:59:22 +00001012 auto sep_idx = path.rfind('/');
Lalit Maganti5f8727d2019-05-24 13:38:50 +01001013 std::string basename =
1014 sep_idx == std::string::npos ? path : path.substr(sep_idx + 1);
1015
1016 auto sql_idx = basename.rfind(".sql");
1017 if (sql_idx == std::string::npos) {
1018 return util::ErrStatus("Unable to find .sql extension for metric");
1019 }
1020 auto no_ext_name = basename.substr(0, sql_idx);
1021
1022 metrics::SqlMetricFile metric;
1023 metric.path = path;
Lalit Magantica4d5142019-05-28 13:25:47 +01001024 metric.sql = stripped_sql;
Deepanjan Roy18044c52020-09-02 17:45:15 -04001025
1026 if (IsRootMetricField(no_ext_name)) {
1027 metric.proto_field_name = no_ext_name;
1028 metric.output_table_name = no_ext_name + "_output";
1029 InsertIntoTraceMetricsTable(*db_, no_ext_name);
1030 }
1031
Lalit Maganti5f8727d2019-05-24 13:38:50 +01001032 sql_metrics_.emplace_back(metric);
1033 return util::OkStatus();
1034}
1035
1036util::Status TraceProcessorImpl::ExtendMetricsProto(const uint8_t* data,
1037 size_t size) {
Deepanjan Roy4ed736c2021-08-12 20:54:02 -04001038 return ExtendMetricsProto(data, size, /*skip_prefixes*/ {});
1039}
1040
1041util::Status TraceProcessorImpl::ExtendMetricsProto(
1042 const uint8_t* data,
1043 size_t size,
1044 const std::vector<std::string>& skip_prefixes) {
1045 util::Status status =
1046 pool_.AddFromFileDescriptorSet(data, size, skip_prefixes);
Lalit Maganti996f5442019-06-21 16:12:58 +01001047 if (!status.ok())
1048 return status;
Lalit Maganti5f8727d2019-05-24 13:38:50 +01001049
Lalit Maganti2553b802019-05-24 13:25:58 +01001050 for (const auto& desc : pool_.descriptors()) {
Lalit Maganti62211072019-05-10 14:09:58 +01001051 // Convert the full name (e.g. .perfetto.protos.TraceMetrics.SubMetric)
1052 // into a function name of the form (TraceMetrics_SubMetric).
1053 auto fn_name = desc.full_name().substr(desc.package_name().size() + 1);
1054 std::replace(fn_name.begin(), fn_name.end(), '.', '_');
Lalit Maganti82517672021-11-04 23:39:15 +00001055 RegisterFunction<metrics::BuildProto>(
1056 db_.get(), fn_name.c_str(), -1,
1057 std::unique_ptr<metrics::BuildProto::Context>(
1058 new metrics::BuildProto::Context{this, &pool_, &desc}));
Lalit Maganti62211072019-05-10 14:09:58 +01001059 }
Lalit Maganti996f5442019-06-21 16:12:58 +01001060 return util::OkStatus();
1061}
Lalit Maganti031ad2b2019-05-14 17:37:14 +01001062
Lalit Maganti996f5442019-06-21 16:12:58 +01001063util::Status TraceProcessorImpl::ComputeMetric(
1064 const std::vector<std::string>& metric_names,
1065 std::vector<uint8_t>* metrics_proto) {
Lalit Maganti2553b802019-05-24 13:25:58 +01001066 auto opt_idx = pool_.FindDescriptorIdx(".perfetto.protos.TraceMetrics");
Lalit Maganti031ad2b2019-05-14 17:37:14 +01001067 if (!opt_idx.has_value())
1068 return util::Status("Root metrics proto descriptor not found");
1069
Lalit Maganti2553b802019-05-24 13:25:58 +01001070 const auto& root_descriptor = pool_.descriptors()[opt_idx.value()];
Lalit Maganti250501a2021-05-20 15:13:31 +01001071 return metrics::ComputeMetrics(this, metric_names, sql_metrics_, pool_,
Lalit Maganti2553b802019-05-24 13:25:58 +01001072 root_descriptor, metrics_proto);
Lalit Magantid9f86b62019-04-08 11:11:51 +01001073}
1074
Deepanjan Roy1e048012020-09-23 12:49:04 -04001075util::Status TraceProcessorImpl::ComputeMetricText(
1076 const std::vector<std::string>& metric_names,
1077 TraceProcessor::MetricResultFormat format,
1078 std::string* metrics_string) {
1079 std::vector<uint8_t> metrics_proto;
1080 util::Status status = ComputeMetric(metric_names, &metrics_proto);
1081 if (!status.ok())
1082 return status;
1083 switch (format) {
1084 case TraceProcessor::MetricResultFormat::kProtoText:
1085 *metrics_string = protozero_to_text::ProtozeroToText(
1086 pool_, ".perfetto.protos.TraceMetrics",
1087 protozero::ConstBytes{metrics_proto.data(), metrics_proto.size()},
1088 protozero_to_text::kIncludeNewLines);
1089 break;
1090 case TraceProcessor::MetricResultFormat::kJson:
1091 // TODO(dproy): Implement this.
1092 PERFETTO_FATAL("Json formatted metrics not supported yet.");
1093 break;
1094 }
1095 return status;
1096}
1097
Deepanjan Roy77747772020-09-01 15:10:33 -04001098std::vector<uint8_t> TraceProcessorImpl::GetMetricDescriptors() {
1099 return pool_.SerializeAsDescriptorSet();
1100}
1101
Lalit Maganti427b8332020-05-27 16:09:45 +01001102void TraceProcessorImpl::EnableMetatrace() {
1103 metatrace::Enable();
1104}
1105
1106util::Status TraceProcessorImpl::DisableAndReadMetatrace(
1107 std::vector<uint8_t>* trace_proto) {
1108 protozero::HeapBuffered<protos::pbzero::Trace> trace;
1109 metatrace::DisableAndReadBuffer([&trace](metatrace::Record* record) {
1110 auto packet = trace->add_packet();
1111 packet->set_timestamp(record->timestamp_ns);
1112 auto* evt = packet->set_perfetto_metatrace();
1113 evt->set_event_name(record->event_name);
1114 evt->set_event_duration_ns(record->duration_ns);
Primiano Tucci1d51ae32020-05-28 09:41:21 +01001115 evt->set_thread_id(1); // Not really important, just required for the ui.
Lalit Maganti427b8332020-05-27 16:09:45 +01001116
1117 if (record->args_buffer_size == 0)
1118 return;
1119
1120 base::StringSplitter s(record->args_buffer, record->args_buffer_size, '\0');
1121 for (; s.Next();) {
1122 auto* arg_proto = evt->add_args();
1123 arg_proto->set_key(s.cur_token());
1124
1125 bool has_next = s.Next();
1126 PERFETTO_CHECK(has_next);
1127 arg_proto->set_value(s.cur_token());
1128 }
1129 });
1130 *trace_proto = trace.SerializeAsArray();
1131 return util::OkStatus();
1132}
1133
Ioannis Ilkoseff38f52018-10-29 10:37:55 +00001134} // namespace trace_processor
1135} // namespace perfetto