blob: 5692b0b3ad329ba885476bed319debb67ff2bfbb [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"
Mikhail Khokhlov81491b92019-12-19 13:58:22 +000026#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
Hector Dearman93b0b092020-01-09 14:35:04 +000027#include "src/trace_processor/metadata_tracker.h"
Mikhail Khokhlov692087e2019-12-11 10:53:45 +000028#include "src/trace_processor/register_additional_modules.h"
Ioannis Ilkoseff38f52018-10-29 10:37:55 +000029#include "src/trace_processor/sched_slice_table.h"
Lalit Maganti95693bb2018-11-05 16:20:24 +000030#include "src/trace_processor/span_join_operator_table.h"
Primiano Tucci5cb84f82018-10-31 21:46:36 -070031#include "src/trace_processor/sql_stats_table.h"
Lalit Maganti40697112019-09-04 22:06:42 +010032#include "src/trace_processor/sqlite/db_sqlite_table.h"
Lalit Maganti03d10622019-08-27 14:47:39 +010033#include "src/trace_processor/sqlite/sqlite3_str_split.h"
Lalit Maganti737b3762019-08-26 13:46:37 -070034#include "src/trace_processor/sqlite/sqlite_table.h"
Lalit Maganti679b29d2020-01-13 13:26:28 +000035#include "src/trace_processor/sqlite_raw_table.h"
Lalit Maganti05e8c132018-11-09 18:16:12 +000036#include "src/trace_processor/stats_table.h"
Lalit Maganti83b53fa2020-01-13 12:55:36 +000037#include "src/trace_processor/types/variadic.h"
Ioannis Ilkoseff38f52018-10-29 10:37:55 +000038#include "src/trace_processor/window_operator_table.h"
39
Eric Secklerc622b8b2019-10-21 09:54:00 +010040#include "src/trace_processor/metrics/metrics.descriptor.h"
41#include "src/trace_processor/metrics/metrics.h"
42#include "src/trace_processor/metrics/sql_metrics.h"
Lalit Maganti26f69bd2019-04-29 18:23:47 +010043
Primiano Tucci02c11762019-08-30 00:57:59 +020044#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010045#include "src/trace_processor/export_json.h"
Lalit Maganti17aa2732019-02-08 15:47:26 +000046#endif
47
Primiano Tuccia1a26de2019-11-12 15:45:19 -080048#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
49#include <cxxabi.h>
50#endif
51
Mikhail Khokhlov8643d1c2019-06-04 12:02:47 +010052// In Android and Chromium tree builds, we don't have the percentile module.
Lalit Maganti17aa2732019-02-08 15:47:26 +000053// Just don't include it.
Primiano Tucci02c11762019-08-30 00:57:59 +020054#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000055// defined in sqlite_src/ext/misc/percentile.c
56extern "C" int sqlite3_percentile_init(sqlite3* db,
57 char** error,
58 const sqlite3_api_routines* api);
Eric Secklera7870e62019-11-01 10:11:58 +000059#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000060
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000061namespace perfetto {
62namespace trace_processor {
Ioannis Ilkos178535e2018-11-05 17:32:45 +000063namespace {
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000064
Primiano Tucci11a79e72019-10-29 22:13:10 +010065const char kAllTablesQuery[] =
66 "SELECT tbl_name, type FROM (SELECT * FROM sqlite_master UNION ALL SELECT "
67 "* FROM sqlite_temp_master)";
68
Ioannis Ilkos7199d552019-03-13 18:35:31 +000069void InitializeSqlite(sqlite3* db) {
70 char* error = nullptr;
71 sqlite3_exec(db, "PRAGMA temp_store=2", 0, 0, &error);
72 if (error) {
73 PERFETTO_FATAL("Error setting pragma temp_store: %s", error);
74 }
Ioannis Ilkosbf54ebb2019-03-08 13:26:14 +000075 sqlite3_str_split_init(db);
Lalit Maganti17aa2732019-02-08 15:47:26 +000076// In Android tree builds, we don't have the percentile module.
77// Just don't include it.
Primiano Tucci02c11762019-08-30 00:57:59 +020078#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
Ioannis Ilkos178535e2018-11-05 17:32:45 +000079 sqlite3_percentile_init(db, &error, nullptr);
Sami Kyostila33668942018-11-13 16:33:32 +000080 if (error) {
Ioannis Ilkos178535e2018-11-05 17:32:45 +000081 PERFETTO_ELOG("Error initializing: %s", error);
Sami Kyostila33668942018-11-13 16:33:32 +000082 sqlite3_free(error);
83 }
Lalit Maganti17aa2732019-02-08 15:47:26 +000084#endif
Sami Kyostila33668942018-11-13 16:33:32 +000085}
86
Lalit Maganti086295b2019-04-04 16:59:19 +010087void BuildBoundsTable(sqlite3* db, std::pair<int64_t, int64_t> bounds) {
88 char* error = nullptr;
89 sqlite3_exec(db, "DELETE FROM trace_bounds", nullptr, nullptr, &error);
90 if (error) {
91 PERFETTO_ELOG("Error deleting from bounds table: %s", error);
92 sqlite3_free(error);
93 return;
94 }
95
96 char* insert_sql = sqlite3_mprintf("INSERT INTO trace_bounds VALUES(%" PRId64
97 ", %" PRId64 ")",
98 bounds.first, bounds.second);
99
100 sqlite3_exec(db, insert_sql, 0, 0, &error);
101 sqlite3_free(insert_sql);
102 if (error) {
103 PERFETTO_ELOG("Error inserting bounds table: %s", error);
104 sqlite3_free(error);
105 }
106}
107
Sami Kyostila33668942018-11-13 16:33:32 +0000108void CreateBuiltinTables(sqlite3* db) {
109 char* error = nullptr;
110 sqlite3_exec(db, "CREATE TABLE perfetto_tables(name STRING)", 0, 0, &error);
111 if (error) {
112 PERFETTO_ELOG("Error initializing: %s", error);
113 sqlite3_free(error);
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000114 }
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000115 sqlite3_exec(db,
116 "CREATE TABLE trace_bounds(start_ts BIG INT, end_ts BIG INT)", 0,
117 0, &error);
118 if (error) {
119 PERFETTO_ELOG("Error initializing: %s", error);
120 sqlite3_free(error);
121 }
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000122
Lalit Maganti086295b2019-04-04 16:59:19 +0100123 // Initialize the bounds table with some data so even before parsing any data,
124 // we still have a valid table.
125 BuildBoundsTable(db, std::make_pair(0, 0));
Ioannis Ilkos178535e2018-11-05 17:32:45 +0000126}
Hector Dearmanc0a29092018-11-08 17:34:23 +0000127
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000128void CreateBuiltinViews(sqlite3* db) {
129 char* error = nullptr;
130 sqlite3_exec(db,
Lalit Maganti809b2f92019-11-07 13:27:26 +0000131 "CREATE VIEW counter_definitions AS "
132 "SELECT "
133 " *, "
Lalit Magantibbc97002019-11-07 17:57:23 +0000134 " id AS counter_id "
Lalit Maganti809b2f92019-11-07 13:27:26 +0000135 "FROM counter_track",
136 0, 0, &error);
137 if (error) {
138 PERFETTO_ELOG("Error initializing: %s", error);
139 sqlite3_free(error);
140 }
141
142 sqlite3_exec(db,
Lalit Maganti69c94442019-11-07 18:59:02 +0000143 "CREATE VIEW counter_values AS "
144 "SELECT "
145 " *, "
146 " track_id as counter_id "
147 "FROM counter",
Lalit Magantibbc97002019-11-07 17:57:23 +0000148 0, 0, &error);
149 if (error) {
150 PERFETTO_ELOG("Error initializing: %s", error);
151 sqlite3_free(error);
152 }
153
154 sqlite3_exec(db,
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000155 "CREATE VIEW counters AS "
Lalit Maganti69c94442019-11-07 18:59:02 +0000156 "SELECT * "
Lalit Magantibbc97002019-11-07 17:57:23 +0000157 "FROM counter_values v "
158 "INNER JOIN counter_track t "
159 "ON v.track_id = t.id "
Lalit Maganti6fbb0ad2019-10-25 14:42:28 +0100160 "ORDER BY ts;",
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000161 0, 0, &error);
162 if (error) {
163 PERFETTO_ELOG("Error initializing: %s", error);
164 sqlite3_free(error);
165 }
Eric Seckler972225e2019-04-18 11:07:12 +0100166
167 sqlite3_exec(db,
168 "CREATE VIEW slice AS "
169 "SELECT "
170 " *, "
Lalit Magantibbc97002019-11-07 17:57:23 +0000171 " category AS cat, "
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000172 " id AS slice_id "
Eric Seckler972225e2019-04-18 11:07:12 +0100173 "FROM internal_slice;",
174 0, 0, &error);
175 if (error) {
176 PERFETTO_ELOG("Error initializing: %s", error);
177 sqlite3_free(error);
178 }
179
Lalit Maganti24b08332019-10-04 12:53:08 +0100180 sqlite3_exec(db,
Lalit Maganti80f566d2020-01-06 13:35:01 +0000181 "CREATE VIEW instants AS "
182 "SELECT "
183 "*, "
184 "0.0 as value "
185 "FROM instant;",
186 0, 0, &error);
187 if (error) {
188 PERFETTO_ELOG("Error initializing: %s", error);
189 sqlite3_free(error);
190 }
191
Eric Seckler972225e2019-04-18 11:07:12 +0100192 // Legacy view for "slice" table with a deprecated table name.
193 // TODO(eseckler): Remove this view when all users have switched to "slice".
194 sqlite3_exec(db,
195 "CREATE VIEW slices AS "
196 "SELECT * FROM slice;",
197 0, 0, &error);
198 if (error) {
199 PERFETTO_ELOG("Error initializing: %s", error);
200 sqlite3_free(error);
201 }
Lalit Magantieac7fff2020-01-10 16:42:54 +0000202
203 sqlite3_exec(db,
204 "CREATE VIEW thread AS "
205 "SELECT "
206 "id as utid, "
207 "* "
208 "FROM internal_thread;",
209 0, 0, &error);
210 if (error) {
211 PERFETTO_ELOG("Error initializing: %s", error);
212 sqlite3_free(error);
213 }
214
215 sqlite3_exec(db,
216 "CREATE VIEW process AS "
217 "SELECT "
218 "id as upid, "
219 "* "
220 "FROM internal_process;",
221 0, 0, &error);
222 if (error) {
223 PERFETTO_ELOG("Error initializing: %s", error);
224 sqlite3_free(error);
225 }
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000226}
227
Primiano Tucci02c11762019-08-30 00:57:59 +0200228#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100229void ExportJson(sqlite3_context* ctx, int /*argc*/, sqlite3_value** argv) {
230 TraceStorage* storage = static_cast<TraceStorage*>(sqlite3_user_data(ctx));
Eric Seckler37ad6af2019-10-08 15:51:14 +0100231 FILE* output;
232 if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
233 // Assume input is an FD.
234 output = fdopen(sqlite3_value_int(argv[0]), "w");
235 if (!output) {
236 sqlite3_result_error(ctx, "Couldn't open output file from given FD", -1);
237 return;
238 }
239 } else {
240 const char* filename =
241 reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
242 output = fopen(filename, "w");
243 if (!output) {
244 sqlite3_result_error(ctx, "Couldn't open output file", -1);
245 return;
246 }
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100247 }
248
Eric Seckler7fb1d232019-10-23 14:42:43 +0100249 util::Status result = json::ExportJson(storage, output);
250 if (!result.ok()) {
251 sqlite3_result_error(ctx, result.message().c_str(), -1);
252 return;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100253 }
254}
255
256void CreateJsonExportFunction(TraceStorage* ts, sqlite3* db) {
257 auto ret = sqlite3_create_function_v2(db, "EXPORT_JSON", 1, SQLITE_UTF8, ts,
258 ExportJson, nullptr, nullptr,
259 sqlite_utils::kSqliteStatic);
260 if (ret) {
261 PERFETTO_ELOG("Error initializing EXPORT_JSON");
262 }
263}
264#endif
265
Lalit Maganti062c8f82019-10-03 20:11:29 +0100266void Hash(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
267 base::Hash hash;
268 for (int i = 0; i < argc; ++i) {
269 sqlite3_value* value = argv[i];
270 switch (sqlite3_value_type(value)) {
271 case SQLITE_INTEGER:
272 hash.Update(sqlite3_value_int64(value));
273 break;
274 case SQLITE_TEXT: {
275 const char* ptr =
276 reinterpret_cast<const char*>(sqlite3_value_text(value));
277 hash.Update(ptr, strlen(ptr));
278 break;
279 }
280 default:
281 sqlite3_result_error(ctx, "Unsupported type of arg passed to HASH", -1);
282 return;
283 }
284 }
285 sqlite3_result_int64(ctx, static_cast<int64_t>(hash.digest()));
286}
287
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000288void Demangle(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
289 if (argc != 1) {
290 sqlite3_result_error(ctx, "Unsupported number of arg passed to DEMANGLE",
291 -1);
292 return;
293 }
294 sqlite3_value* value = argv[0];
295 if (sqlite3_value_type(value) != SQLITE_TEXT) {
296 sqlite3_result_error(ctx, "Unsupported type of arg passed to DEMANGLE", -1);
297 return;
298 }
299 const char* ptr = reinterpret_cast<const char*>(sqlite3_value_text(value));
Primiano Tuccia1a26de2019-11-12 15:45:19 -0800300#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000301 int ignored = 0;
302 // This memory was allocated by malloc and will be passed to SQLite to free.
303 char* demangled_name = abi::__cxa_demangle(ptr, nullptr, nullptr, &ignored);
304 if (!demangled_name) {
305 sqlite3_result_null(ctx);
306 return;
307 }
308 sqlite3_result_text(ctx, demangled_name, -1, free);
Primiano Tuccia1a26de2019-11-12 15:45:19 -0800309#else
310 sqlite3_result_text(ctx, ptr, -1, sqlite_utils::kSqliteTransient);
311#endif
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000312}
313
Lalit Maganti062c8f82019-10-03 20:11:29 +0100314void CreateHashFunction(sqlite3* db) {
315 auto ret = sqlite3_create_function_v2(
316 db, "HASH", -1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &Hash,
317 nullptr, nullptr, nullptr);
318 if (ret) {
319 PERFETTO_ELOG("Error initializing HASH");
320 }
321}
322
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000323void CreateDemangledNameFunction(sqlite3* db) {
324 auto ret = sqlite3_create_function_v2(
325 db, "DEMANGLE", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &Demangle,
326 nullptr, nullptr, nullptr);
327 if (ret != SQLITE_OK) {
328 PERFETTO_ELOG("Error initializing DEMANGLE: %s", sqlite3_errmsg(db));
329 }
330}
331
Lalit Maganti2553b802019-05-24 13:25:58 +0100332void SetupMetrics(TraceProcessor* tp,
333 sqlite3* db,
Lalit Maganti2553b802019-05-24 13:25:58 +0100334 std::vector<metrics::SqlMetricFile>* sql_metrics) {
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100335 tp->ExtendMetricsProto(kMetricsDescriptor.data(), kMetricsDescriptor.size());
336
Lalit Maganti2553b802019-05-24 13:25:58 +0100337 for (const auto& file_to_sql : metrics::sql_metrics::kFileToSql) {
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100338 tp->RegisterMetric(file_to_sql.path, file_to_sql.sql);
Lalit Maganti2553b802019-05-24 13:25:58 +0100339 }
340
341 {
342 std::unique_ptr<metrics::RunMetricContext> ctx(
343 new metrics::RunMetricContext());
344 ctx->tp = tp;
345 ctx->metrics = sql_metrics;
346 auto ret = sqlite3_create_function_v2(
347 db, "RUN_METRIC", -1, SQLITE_UTF8, ctx.release(), metrics::RunMetric,
348 nullptr, nullptr,
349 [](void* ptr) { delete static_cast<metrics::RunMetricContext*>(ptr); });
350 if (ret)
351 PERFETTO_ELOG("Error initializing RUN_METRIC");
352 }
353
354 {
355 auto ret = sqlite3_create_function_v2(
356 db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr,
357 metrics::RepeatedFieldStep, metrics::RepeatedFieldFinal, nullptr);
358 if (ret)
359 PERFETTO_ELOG("Error initializing RepeatedField");
360 }
361}
Hector Dearmanc0a29092018-11-08 17:34:23 +0000362} // namespace
363
Eric Secklera7870e62019-11-01 10:11:58 +0000364TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
365 : TraceProcessorStorageImpl(cfg) {
Mikhail Khokhlov692087e2019-12-11 10:53:45 +0000366 RegisterAdditionalModules(&context_);
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000367 sqlite3* db = nullptr;
Mikhail Khokhlov4a911282019-05-31 14:25:07 +0100368 PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000369 PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
Ioannis Ilkos7199d552019-03-13 18:35:31 +0000370 InitializeSqlite(db);
Sami Kyostila33668942018-11-13 16:33:32 +0000371 CreateBuiltinTables(db);
Lalit Maganti8320e6d2019-03-14 18:49:33 +0000372 CreateBuiltinViews(db);
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000373 db_.reset(std::move(db));
374
Primiano Tucci02c11762019-08-30 00:57:59 +0200375#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100376 CreateJsonExportFunction(this->context_.storage.get(), db);
377#endif
Lalit Maganti062c8f82019-10-03 20:11:29 +0100378 CreateHashFunction(db);
Neda Topoljanacc2aecf72019-11-12 14:11:19 +0000379 CreateDemangledNameFunction(db);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100380
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100381 SetupMetrics(this, *db_, &sql_metrics_);
Lalit Maganti2553b802019-05-24 13:25:58 +0100382
Lalit Maganti786cc922019-09-06 16:04:32 +0100383 const TraceStorage* storage = context_.storage.get();
Lalit Maganti809b2f92019-11-07 13:27:26 +0000384
Lalit Maganti679b29d2020-01-13 13:26:28 +0000385 SchedSliceTable::RegisterTable(*db_, storage);
386 SqlStatsTable::RegisterTable(*db_, storage);
387 SpanJoinOperatorTable::RegisterTable(*db_, storage);
388 WindowOperatorTable::RegisterTable(*db_, storage);
389 StatsTable::RegisterTable(*db_, storage);
390
391 // New style tables but with some custom logic.
392 SqliteRawTable::RegisterTable(*db_, context_.storage.get());
393
394 // New style db-backed tables.
Lalit Maganti1908e262020-01-09 14:33:19 +0000395 DbSqliteTable::RegisterTable(*db_, &storage->arg_table(),
396 storage->arg_table().table_name());
Lalit Magantieac7fff2020-01-10 16:42:54 +0000397 DbSqliteTable::RegisterTable(*db_, &storage->thread_table(),
398 storage->thread_table().table_name());
399 DbSqliteTable::RegisterTable(*db_, &storage->process_table(),
400 storage->process_table().table_name());
Lalit Maganti1908e262020-01-09 14:33:19 +0000401
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000402 DbSqliteTable::RegisterTable(*db_, &storage->slice_table(),
403 storage->slice_table().table_name());
Lalit Maganti80f566d2020-01-06 13:35:01 +0000404 DbSqliteTable::RegisterTable(*db_, &storage->instant_table(),
405 storage->instant_table().table_name());
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000406 DbSqliteTable::RegisterTable(*db_, &storage->gpu_slice_table(),
407 storage->gpu_slice_table().table_name());
408
Lalit Magantiac68e9c2019-09-09 18:12:15 +0100409 DbSqliteTable::RegisterTable(*db_, &storage->track_table(),
410 storage->track_table().table_name());
Lalit Maganti21b21632019-09-28 16:50:23 +0100411 DbSqliteTable::RegisterTable(*db_, &storage->thread_track_table(),
412 storage->thread_track_table().table_name());
Lalit Maganti53bdbb22019-09-25 11:11:18 +0100413 DbSqliteTable::RegisterTable(*db_, &storage->process_track_table(),
414 storage->process_track_table().table_name());
Lalit Maganti786cc922019-09-06 16:04:32 +0100415 DbSqliteTable::RegisterTable(*db_, &storage->gpu_track_table(),
Lalit Magantiac68e9c2019-09-09 18:12:15 +0100416 storage->gpu_track_table().table_name());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000417
Lalit Maganti4b3b3ad2019-12-04 19:27:35 +0000418 DbSqliteTable::RegisterTable(*db_, &storage->counter_table(),
419 storage->counter_table().table_name());
420
Lalit Maganti809b2f92019-11-07 13:27:26 +0000421 DbSqliteTable::RegisterTable(*db_, &storage->counter_track_table(),
422 storage->counter_track_table().table_name());
423 DbSqliteTable::RegisterTable(
424 *db_, &storage->process_counter_track_table(),
425 storage->process_counter_track_table().table_name());
426 DbSqliteTable::RegisterTable(
427 *db_, &storage->thread_counter_track_table(),
428 storage->thread_counter_track_table().table_name());
429 DbSqliteTable::RegisterTable(*db_, &storage->cpu_counter_track_table(),
430 storage->cpu_counter_track_table().table_name());
431 DbSqliteTable::RegisterTable(*db_, &storage->irq_counter_track_table(),
432 storage->irq_counter_track_table().table_name());
433 DbSqliteTable::RegisterTable(
434 *db_, &storage->softirq_counter_track_table(),
435 storage->softirq_counter_track_table().table_name());
436 DbSqliteTable::RegisterTable(*db_, &storage->gpu_counter_track_table(),
437 storage->gpu_counter_track_table().table_name());
438
Florian Mayer25e013e2019-10-01 14:06:15 +0100439 DbSqliteTable::RegisterTable(*db_, &storage->heap_graph_object_table(),
440 storage->heap_graph_object_table().table_name());
Mohammad Reza Zakerinasabb06d1852019-09-11 14:41:36 -0400441 DbSqliteTable::RegisterTable(
Florian Mayer9c01d162019-10-09 17:55:32 +0100442 *db_, &storage->heap_graph_reference_table(),
443 storage->heap_graph_reference_table().table_name());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000444
445 DbSqliteTable::RegisterTable(*db_, &storage->symbol_table(),
446 storage->symbol_table().table_name());
447 DbSqliteTable::RegisterTable(
Lalit Magantia5ffb202019-12-17 18:10:52 +0000448 *db_, &storage->heap_profile_allocation_table(),
449 storage->heap_profile_allocation_table().table_name());
450 DbSqliteTable::RegisterTable(
Florian Mayerb6652092020-01-13 13:47:35 +0000451 *db_, &storage->experimental_heap_graph_allocation_table(),
452 storage->experimental_heap_graph_allocation_table().table_name());
Florian Mayer46f16972020-01-10 16:23:30 +0000453 DbSqliteTable::RegisterTable(
Lalit Maganti0fd14ef2019-12-18 18:18:44 +0000454 *db_, &storage->cpu_profile_stack_sample_table(),
455 storage->cpu_profile_stack_sample_table().table_name());
456 DbSqliteTable::RegisterTable(
Lalit Maganti809b2f92019-11-07 13:27:26 +0000457 *db_, &storage->stack_profile_callsite_table(),
458 storage->stack_profile_callsite_table().table_name());
Lalit Maganti45980c92019-12-20 13:17:44 +0000459 DbSqliteTable::RegisterTable(
460 *db_, &storage->stack_profile_mapping_table(),
461 storage->stack_profile_mapping_table().table_name());
Lalit Maganti0a29f6f2020-01-06 12:01:14 +0000462 DbSqliteTable::RegisterTable(
463 *db_, &storage->stack_profile_frame_table(),
464 storage->stack_profile_frame_table().table_name());
Lalit Maganti809b2f92019-11-07 13:27:26 +0000465
Lalit Magantif1ab24f2020-01-07 17:42:26 +0000466 DbSqliteTable::RegisterTable(*db_, &storage->android_log_table(),
467 storage->android_log_table().table_name());
468
Florian Mayer9c01d162019-10-09 17:55:32 +0100469 DbSqliteTable::RegisterTable(
Mohammad Reza Zakerinasabb06d1852019-09-11 14:41:36 -0400470 *db_, &storage->vulkan_memory_allocations_table(),
471 storage->vulkan_memory_allocations_table().table_name());
Lalit Magantiededb0e2020-01-08 12:50:34 +0000472
473 DbSqliteTable::RegisterTable(*db_, &storage->metadata_table(),
474 storage->metadata_table().table_name());
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000475}
476
Lalit Maganti77095012019-02-19 13:13:59 +0000477TraceProcessorImpl::~TraceProcessorImpl() {
478 for (auto* it : iterators_)
479 it->Reset();
480}
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000481
Lalit Maganti1f067182019-05-09 14:50:05 +0100482util::Status TraceProcessorImpl::Parse(std::unique_ptr<uint8_t[]> data,
483 size_t size) {
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100484 bytes_parsed_ += size;
Eric Secklera7870e62019-11-01 10:11:58 +0000485 return TraceProcessorStorageImpl::Parse(std::move(data), size);
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000486}
487
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100488std::string TraceProcessorImpl::GetCurrentTraceName() {
489 if (current_trace_name_.empty())
490 return "";
491 auto size = " (" + std::to_string(bytes_parsed_ / 1024 / 1024) + " MB)";
492 return current_trace_name_ + size;
493}
494
495void TraceProcessorImpl::SetCurrentTraceName(const std::string& name) {
496 current_trace_name_ = name;
497}
498
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000499void TraceProcessorImpl::NotifyEndOfFile() {
Primiano Tucciee2ce1d2019-11-01 19:14:17 +0100500 if (current_trace_name_.empty())
501 current_trace_name_ = "Unnamed trace";
502
Eric Secklera7870e62019-11-01 10:11:58 +0000503 TraceProcessorStorageImpl::NotifyEndOfFile();
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700504
Mikhail Khokhlov81491b92019-12-19 13:58:22 +0000505 SchedEventTracker::GetOrCreate(&context_)->FlushPendingEvents();
Hector Dearman93b0b092020-01-09 14:35:04 +0000506 context_.metadata_tracker->SetMetadata(
507 metadata::trace_size_bytes,
508 Variadic::Integer(static_cast<int64_t>(bytes_parsed_)));
Ioannis Ilkosb8b11102019-01-29 17:56:55 +0000509 BuildBoundsTable(*db_, context_.storage->GetTraceTimestampBoundsNs());
Primiano Tucci11a79e72019-10-29 22:13:10 +0100510
511 // Create a snapshot of all tables and views created so far. This is so later
512 // we can drop all extra tables created by the UI and reset to the original
513 // state (see RestoreInitialTables).
514 initial_tables_.clear();
515 auto it = ExecuteQuery(kAllTablesQuery);
516 while (it.Next()) {
517 auto value = it.Get(0);
518 PERFETTO_CHECK(value.type == SqlValue::Type::kString);
519 initial_tables_.push_back(value.string_value);
520 }
521}
522
523size_t TraceProcessorImpl::RestoreInitialTables() {
524 std::vector<std::pair<std::string, std::string>> deletion_list;
525 std::string msg = "Resetting DB to initial state, deleting table/views:";
526 for (auto it = ExecuteQuery(kAllTablesQuery); it.Next();) {
527 std::string name(it.Get(0).string_value);
528 std::string type(it.Get(1).string_value);
529 if (std::find(initial_tables_.begin(), initial_tables_.end(), name) ==
530 initial_tables_.end()) {
531 msg += " " + name;
532 deletion_list.push_back(std::make_pair(type, name));
533 }
534 }
535
536 PERFETTO_LOG("%s", msg.c_str());
537 for (const auto& tn : deletion_list) {
538 std::string query = "DROP " + tn.first + " " + tn.second;
539 auto it = ExecuteQuery(query);
540 while (it.Next()) {
541 }
542 PERFETTO_CHECK(it.Status().ok());
543 }
544 return deletion_list.size();
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000545}
546
Lalit Maganti77095012019-02-19 13:13:59 +0000547TraceProcessor::Iterator TraceProcessorImpl::ExecuteQuery(
Lalit Magantiaac2f652019-04-30 12:16:21 +0100548 const std::string& sql,
549 int64_t time_queued) {
Lalit Maganti77095012019-02-19 13:13:59 +0000550 sqlite3_stmt* raw_stmt;
Lalit Maganti73b1a0a2019-04-08 13:51:14 +0100551 int err = sqlite3_prepare_v2(*db_, sql.c_str(), static_cast<int>(sql.size()),
Lalit Maganti77095012019-02-19 13:13:59 +0000552 &raw_stmt, nullptr);
Lalit Maganti1f067182019-05-09 14:50:05 +0100553 util::Status status;
Lalit Maganti06acc022019-04-03 16:02:15 +0100554 uint32_t col_count = 0;
555 if (err != SQLITE_OK) {
Lalit Maganti7ee6abb2019-05-09 17:57:32 +0100556 status = util::ErrStatus("%s", sqlite3_errmsg(*db_));
Lalit Maganti77095012019-02-19 13:13:59 +0000557 } else {
558 col_count = static_cast<uint32_t>(sqlite3_column_count(raw_stmt));
559 }
Lalit Magantiaac2f652019-04-30 12:16:21 +0100560
561 base::TimeNanos t_start = base::GetWallTimeNs();
562 uint32_t sql_stats_row =
563 context_.storage->mutable_sql_stats()->RecordQueryBegin(sql, time_queued,
564 t_start.count());
565
566 std::unique_ptr<IteratorImpl> impl(new IteratorImpl(
Lalit Maganti1f067182019-05-09 14:50:05 +0100567 this, *db_, ScopedStmt(raw_stmt), col_count, status, sql_stats_row));
Lalit Maganti77095012019-02-19 13:13:59 +0000568 iterators_.emplace_back(impl.get());
569 return TraceProcessor::Iterator(std::move(impl));
570}
571
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000572void TraceProcessorImpl::InterruptQuery() {
573 if (!db_)
574 return;
575 query_interrupted_.store(true);
576 sqlite3_interrupt(db_.get());
577}
578
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100579util::Status TraceProcessorImpl::RegisterMetric(const std::string& path,
580 const std::string& sql) {
Lalit Magantif9d80302019-06-19 12:48:25 +0100581 std::string stripped_sql;
582 for (base::StringSplitter sp(sql, '\n'); sp.Next();) {
583 if (strncmp(sp.cur_token(), "--", 2) != 0) {
584 stripped_sql.append(sp.cur_token());
585 stripped_sql.push_back('\n');
586 }
587 }
588
589 // Check if the metric with the given path already exists and if it does, just
590 // update the SQL associated with it.
591 auto it = std::find_if(
592 sql_metrics_.begin(), sql_metrics_.end(),
593 [&path](const metrics::SqlMetricFile& m) { return m.path == path; });
594 if (it != sql_metrics_.end()) {
595 it->sql = stripped_sql;
596 return util::OkStatus();
597 }
598
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100599 auto sep_idx = path.rfind("/");
600 std::string basename =
601 sep_idx == std::string::npos ? path : path.substr(sep_idx + 1);
602
603 auto sql_idx = basename.rfind(".sql");
604 if (sql_idx == std::string::npos) {
605 return util::ErrStatus("Unable to find .sql extension for metric");
606 }
607 auto no_ext_name = basename.substr(0, sql_idx);
608
609 metrics::SqlMetricFile metric;
610 metric.path = path;
611 metric.proto_field_name = no_ext_name;
612 metric.output_table_name = no_ext_name + "_output";
Lalit Magantica4d5142019-05-28 13:25:47 +0100613 metric.sql = stripped_sql;
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100614 sql_metrics_.emplace_back(metric);
615 return util::OkStatus();
616}
617
618util::Status TraceProcessorImpl::ExtendMetricsProto(const uint8_t* data,
619 size_t size) {
Lalit Maganti996f5442019-06-21 16:12:58 +0100620 util::Status status = pool_.AddFromFileDescriptorSet(data, size);
621 if (!status.ok())
622 return status;
Lalit Maganti5f8727d2019-05-24 13:38:50 +0100623
Lalit Maganti2553b802019-05-24 13:25:58 +0100624 for (const auto& desc : pool_.descriptors()) {
Lalit Maganti62211072019-05-10 14:09:58 +0100625 // Convert the full name (e.g. .perfetto.protos.TraceMetrics.SubMetric)
626 // into a function name of the form (TraceMetrics_SubMetric).
627 auto fn_name = desc.full_name().substr(desc.package_name().size() + 1);
628 std::replace(fn_name.begin(), fn_name.end(), '.', '_');
629
Lalit Magantib182d7e2019-05-10 14:13:06 +0100630 std::unique_ptr<metrics::BuildProtoContext> ctx(
631 new metrics::BuildProtoContext());
632 ctx->tp = this;
Lalit Maganti2553b802019-05-24 13:25:58 +0100633 ctx->pool = &pool_;
Lalit Magantib182d7e2019-05-10 14:13:06 +0100634 ctx->desc = &desc;
635
Lalit Maganti62211072019-05-10 14:09:58 +0100636 auto ret = sqlite3_create_function_v2(
Lalit Magantib182d7e2019-05-10 14:13:06 +0100637 *db_, fn_name.c_str(), -1, SQLITE_UTF8, ctx.release(),
638 metrics::BuildProto, nullptr, nullptr, [](void* ptr) {
639 delete static_cast<metrics::BuildProtoContext*>(ptr);
640 });
Lalit Maganti62211072019-05-10 14:09:58 +0100641 if (ret != SQLITE_OK)
642 return util::ErrStatus("%s", sqlite3_errmsg(*db_));
643 }
Lalit Maganti996f5442019-06-21 16:12:58 +0100644 return util::OkStatus();
645}
Lalit Maganti031ad2b2019-05-14 17:37:14 +0100646
Lalit Maganti996f5442019-06-21 16:12:58 +0100647util::Status TraceProcessorImpl::ComputeMetric(
648 const std::vector<std::string>& metric_names,
649 std::vector<uint8_t>* metrics_proto) {
Lalit Maganti2553b802019-05-24 13:25:58 +0100650 auto opt_idx = pool_.FindDescriptorIdx(".perfetto.protos.TraceMetrics");
Lalit Maganti031ad2b2019-05-14 17:37:14 +0100651 if (!opt_idx.has_value())
652 return util::Status("Root metrics proto descriptor not found");
653
Lalit Maganti2553b802019-05-24 13:25:58 +0100654 const auto& root_descriptor = pool_.descriptors()[opt_idx.value()];
655 return metrics::ComputeMetrics(this, metric_names, sql_metrics_,
656 root_descriptor, metrics_proto);
Lalit Magantid9f86b62019-04-08 11:11:51 +0100657}
658
Lalit Maganti77095012019-02-19 13:13:59 +0000659TraceProcessor::IteratorImpl::IteratorImpl(TraceProcessorImpl* trace_processor,
660 sqlite3* db,
661 ScopedStmt stmt,
662 uint32_t column_count,
Lalit Maganti1f067182019-05-09 14:50:05 +0100663 util::Status status,
Lalit Magantiaac2f652019-04-30 12:16:21 +0100664 uint32_t sql_stats_row)
Lalit Maganti77095012019-02-19 13:13:59 +0000665 : trace_processor_(trace_processor),
666 db_(db),
667 stmt_(std::move(stmt)),
668 column_count_(column_count),
Lalit Maganti1f067182019-05-09 14:50:05 +0100669 status_(status),
Lalit Magantiaac2f652019-04-30 12:16:21 +0100670 sql_stats_row_(sql_stats_row) {}
Lalit Maganti77095012019-02-19 13:13:59 +0000671
672TraceProcessor::IteratorImpl::~IteratorImpl() {
673 if (trace_processor_) {
674 auto* its = &trace_processor_->iterators_;
675 auto it = std::find(its->begin(), its->end(), this);
676 PERFETTO_CHECK(it != its->end());
677 its->erase(it);
Lalit Magantiaac2f652019-04-30 12:16:21 +0100678
679 base::TimeNanos t_end = base::GetWallTimeNs();
680 auto* sql_stats = trace_processor_->context_.storage->mutable_sql_stats();
681 sql_stats->RecordQueryEnd(sql_stats_row_, t_end.count());
Lalit Maganti77095012019-02-19 13:13:59 +0000682 }
683}
684
685void TraceProcessor::IteratorImpl::Reset() {
Lalit Maganti1f067182019-05-09 14:50:05 +0100686 *this = IteratorImpl(nullptr, nullptr, ScopedStmt(), 0,
687 util::ErrStatus("Trace processor was deleted"), 0);
Lalit Magantiaac2f652019-04-30 12:16:21 +0100688}
689
690void TraceProcessor::IteratorImpl::RecordFirstNextInSqlStats() {
691 base::TimeNanos t_first_next = base::GetWallTimeNs();
692 auto* sql_stats = trace_processor_->context_.storage->mutable_sql_stats();
693 sql_stats->RecordQueryFirstNext(sql_stats_row_, t_first_next.count());
Lalit Maganti77095012019-02-19 13:13:59 +0000694}
695
Ioannis Ilkoseff38f52018-10-29 10:37:55 +0000696} // namespace trace_processor
697} // namespace perfetto