blob: eda0116d7cac5a40ed01e1ae25e5e36a68ba95cb [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include <functional>
#include "perfetto/base/logging.h"
#include "perfetto/base/time.h"
#include "perfetto/base/unix_task_runner.h"
#include "src/trace_processor/file_reader.h"
#include "src/trace_processor/trace_processor.h"
#include "perfetto/trace_processor/raw_query.pb.h"
using namespace perfetto;
using namespace perfetto::trace_processor;
namespace {
void PrintPrompt() {
printf("\r%80s\r> ", "");
fflush(stdout);
}
void OnQueryResult(base::TimeNanos t_start, const protos::RawQueryResult& res) {
PERFETTO_CHECK(res.columns_size() == res.column_descriptors_size());
if (res.has_error()) {
PERFETTO_ELOG("SQLite error: %s", res.error().c_str());
return;
}
base::TimeNanos t_end = base::GetWallTimeNs();
for (int r = 0; r < static_cast<int>(res.num_records()); r++) {
if (r % 32 == 0) {
if (r > 0) {
fprintf(stderr, "...\nType 'q' to stop, Enter for more records: ");
fflush(stderr);
char input[32];
if (!fgets(input, sizeof(input) - 1, stdin))
exit(0);
if (input[0] == 'q')
break;
}
for (const auto& col : res.column_descriptors())
printf("%20s ", col.name().c_str());
printf("\n");
for (int i = 0; i < res.columns_size(); i++)
printf("%20s ", "--------------------");
printf("\n");
}
for (int c = 0; c < res.columns_size(); c++) {
switch (res.column_descriptors(c).type()) {
case protos::RawQueryResult_ColumnDesc_Type_STRING:
printf("%20s ", res.columns(c).string_values(r).c_str());
break;
case protos::RawQueryResult_ColumnDesc_Type_DOUBLE:
printf("%20f ", res.columns(c).double_values(r));
break;
case protos::RawQueryResult_ColumnDesc_Type_LONG:
printf("%20lld ", res.columns(c).long_values(r));
break;
}
}
printf("\n");
}
printf("\nQuery executed in %.3f ms\n\n", (t_end - t_start).count() / 1E6);
}
} // namespace
int main(int argc, char** argv) {
if (argc < 2) {
PERFETTO_ELOG("Usage: %s trace_file.proto", argv[0]);
return 1;
}
base::UnixTaskRunner task_runner;
FileReader reader(argv[1]);
TraceProcessor tp(&task_runner);
task_runner.PostTask([&tp, &reader]() {
auto t_start = base::GetWallTimeMs();
auto on_trace_loaded = [t_start, &reader] {
double s = (base::GetWallTimeMs() - t_start).count() / 1000.0;
double size_mb = reader.file_size() / 1000000.0;
PERFETTO_ILOG("Trace loaded: %.2f MB (%.1f MB/s)", size_mb, size_mb / s);
PrintPrompt();
};
tp.LoadTrace(&reader, on_trace_loaded);
});
task_runner.AddFileDescriptorWatch(STDIN_FILENO, [&tp, &task_runner] {
char line[1024];
if (!fgets(line, sizeof(line) - 1, stdin)) {
task_runner.Quit();
return;
}
protos::RawQueryArgs query;
query.set_sql_query(line);
base::TimeNanos t_start = base::GetWallTimeNs();
tp.ExecuteQuery(query, [t_start](const protos::RawQueryResult& res) {
OnQueryResult(t_start, res);
});
PrintPrompt();
});
task_runner.Run();
return 0;
}