summaryrefslogtreecommitdiff
path: root/src/perfetto/main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/perfetto/main.cc')
-rw-r--r--src/perfetto/main.cc244
1 files changed, 0 insertions, 244 deletions
diff --git a/src/perfetto/main.cc b/src/perfetto/main.cc
deleted file mode 100644
index 0b1056e..0000000
--- a/src/perfetto/main.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// 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.
-
-//#undef NDEBUG // get DCHECK etc.
-
-
-#include "common/debug.h"
-#include "common/expected.h"
-#include "perfetto/rx_producer.h"
-
-#include <android-base/unique_fd.h>
-#include <android-base/parseint.h>
-#include <android-base/file.h>
-
-#include "rxcpp/rx.hpp"
-#include <iostream>
-#include <optional>
-
-#include <sched.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <syscall.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-using namespace iorap::perfetto; // NOLINT
-
-#if defined(IORAP_PERFETTO_MAIN)
-
-void Usage(char** argv) {
- std::cerr << "Usage: " << argv[0] << " [--config-proto=config.pb] [--duration-ms=5000] [--output-proto=output.pb]" << std::endl;
- std::cerr << "" << std::endl;
- std::cerr << " Request a perfetto trace, blocking until it's complete. The resulting trace proto" << std::endl;
- std::cerr << " is output to stdout as text, or to --output-proto as a binary." << std::endl;
- std::cerr << "" << std::endl;
- std::cerr << " Optional flags:" << std::endl;
- std::cerr << " --help,-h Print this Usage." << std::endl;
- std::cerr << " --output-proto $,-op $ Perfetto tracebuffer output file (default stdout)." << std::endl;
- std::cerr << " --config-proto $,-cp $ Path to binary protobuf config." << std::endl;
- std::cerr << " --duration-ms $,-dm $ How long to run trace for in milliseconds." << std::endl;
- std::cerr << " --simple Simplest possible perfetto state transitions (default off)." << std::endl;
- std::cerr << " --verbose,-v Set verbosity (default off)." << std::endl;
- std::cerr << " --wait,-w Wait for key stroke before continuing (default off)." << std::endl;
- exit(1);
-}
-
-PerfettoDependencies::Component CreateCommandLinePerfettoDependenciesComponent(
- uint32_t duration_ms) {
- // TODO: read from command line.
- static const uint32_t kBufferSize = 4096;
-
- // TODO: remove this hack.
- static const uint32_t kTraceDurationMs = duration_ms;
-
- // fruit: using 'bindInstance' causes a segfault every time.
-#if 0
-
- // fruit: Can't use a stateful lambda, so use bindInstance instead of registerProvider.
- auto config = PerfettoDependencies::CreateConfig(duration_ms,
- /*deferred_start*/true,
- kBufferSize);
-
- .... bindInstance(config);
-#endif
-
- return fruit::createComponent()
- .bind<PerfettoConsumer, PerfettoConsumerImpl>()
- .registerProvider([]() /* -> TraceConfig */ {
- return PerfettoDependencies::CreateConfig(kTraceDurationMs,
- /*deferred_start*/true,
- kBufferSize);
- });
-}
-
-static void CollectPerfettoTraceBufferViaAbstractions(
- RxProducerFactory& producer_factory,
- const std::string& arg_output_proto,
- const int arg_duration_ms) {
- LOG(VERBOSE) << "CollectPerfettoTraceBufferViaAbstractions";
-
- // Don't create a subscriber to emit the PerfettoStreamCommand.
- // RxCpp is "greedy" and consumes every possible item emitted (it doesn't support 'pull'). We want
- // to operate on a (command,state) iteration every time, just like in a real scenario.
- // Adding the 'interval' turns into a non-greedy version (i.e. push).
-
- // Immediately emit 'kStartTracing', wait and emit kStopTracing, wait and emit kShutdown.
- // In reality, there would be a delay between all these events.
- auto /*observable<PerfettoStreamCommand>*/ commands =
- rxcpp::observable<>::just(PerfettoStreamCommand::kStartTracing)
- // wait 1x
- .concat(
- // Pick a value longer than the perfetto config delay_ms, so that we send
- // 'kShutdown' after tracing has already finished.
- rxcpp::observable<>::interval(std::chrono::milliseconds(arg_duration_ms * 2))
- .take(2) // kStopTracing, kShutdown.
- .map([](int value) {
- // value is 1,2,3,...
- return static_cast<PerfettoStreamCommand>(value); // 1,2, ...
- })
- );
-
- auto /*observable<PerfettoTraceProto>*/ trace_proto_stream =
- producer_factory.CreateTraceStream(commands);
-
- trace_proto_stream
- .observe_on(ObserveOnNewIoThread()) // Write data on an idle-class-priority thread.
- .as_blocking() // Wait for observable to terminate with on_completed or on_error.
- .subscribe(/*on_next*/[arg_output_proto]
- (PerfettoTraceProto trace_proto) {
- if (!trace_proto.WriteFullyToFile(arg_output_proto)) {
- LOG(ERROR) << "Failed to save TraceBuffer to " << arg_output_proto;
- } else {
- LOG(INFO) << "TraceBuffer saved to file: " << arg_output_proto;
- LOG(INFO);
- LOG(INFO) << "To print this in a human readable form, execute these commands:";
- LOG(INFO) << "$> adb pull '" << arg_output_proto << "'";
- LOG(INFO) << "$> trace_to_text systrace <filename.pb>";
- }
- },
- /*on_error*/[](rxcpp::util::error_ptr err) {
- LOG(ERROR) << "Perfetto trace proto collection error: " << rxcpp::util::what(err);
- });
-}
-
-namespace iorap::perfetto {
-// Reach inside rx_producer.cc
-// Not part of any headers because it's internal.
-void CollectPerfettoTraceBufferImmediately(
- RxProducerFactory& producer_factory,
- const std::string& arg_output_proto);
-}
-
-int main(int argc, char** argv) {
- android::base::InitLogging(argv);
- android::base::SetLogger(android::base::StderrLogger);
-
- bool wait_for_keystroke = false;
- bool enable_verbose = false;
-
- std::string arg_output_proto;
- std::string arg_config_proto;
- uint32_t arg_duration_ms = 1000;
- bool arg_simple = false;
-
- if (argc == 1) {
- Usage(argv);
- }
-
- for (int arg = 1; arg < argc; ++arg) {
- std::string argstr = argv[arg];
- bool has_arg_next = (arg+1)<argc;
- std::string arg_next = has_arg_next ? argv[arg+1] : "";
-
- if (argstr == "--help" || argstr == "-h") {
- Usage(argv);
- } else if (argstr == "--output-proto" || argstr == "-op") {
- if (!has_arg_next) {
- std::cerr << "Missing --output-proto <value>" << std::endl;
- return 1;
- }
- arg_output_proto = arg_next;
- ++arg;
- } else if (argstr == "--config-proto" || argstr == "-cp") {
- if (!has_arg_next) {
- std::cerr << "Missing --config-proto <value>" << std::endl;
- return 1;
- }
- arg_config_proto = arg_next;
- LOG(WARNING) << "TODO: parse configs from a file, not implemented yet.";
- ++arg;
- } else if (argstr == "--duration-ms" || argstr == "-dm") {
- if (!has_arg_next) {
- std::cerr << "Missing --duration-ms <value>" << std::endl;
- return 1;
- }
- if (!android::base::ParseUint(arg_next.c_str(), /*out*/&arg_duration_ms)) {
- std::cerr << "Invalid --duration-ms " << arg_next << ", reason: " << strerror(errno);
- return 1;
- }
- ++arg;
- } else if (argstr == "--simple") {
- arg_simple = true;
- } else if (argstr == "--verbose" || argstr == "-v") {
- enable_verbose = true;
- } else if (argstr == "--wait" || argstr == "-w") {
- wait_for_keystroke = true;
- }
- }
-
- if (enable_verbose) {
- android::base::SetMinimumLogSeverity(android::base::VERBOSE);
-
- LOG(VERBOSE) << "Verbose check";
- LOG(VERBOSE) << "Debug check: " << ::iorap::kIsDebugBuild;
- }
-
- // Useful to attach a debugger...
- // 1) $> iorap-cmd-perfetto -w <args>
- // 2) $> gdbclient <pid>
- if (wait_for_keystroke) {
- LOG(INFO) << "Self pid: " << getpid();
- LOG(INFO) << "Press any key to continue...";
- std::cin >> wait_for_keystroke;
- }
-
- int return_code = 0;
- // TODO: convert #on-error into a non-0 return code.
-
- PerfettoDependencies::Injector injector{
- CreateCommandLinePerfettoDependenciesComponent,
- arg_duration_ms
- };
- RxProducerFactory rx_producer_factory{/*borrow*/injector};
-
- if (arg_simple) {
- // To debug any kind of low-level perfetto issues.
- CollectPerfettoTraceBufferImmediately(/*inout*/rx_producer_factory, arg_output_proto);
- } else {
- // To debug our own iorap internal abstractions.
- CollectPerfettoTraceBufferViaAbstractions(/*inout*/rx_producer_factory,
- arg_output_proto,
- arg_duration_ms);
- }
-
- // Uncomment this if we want to leave the process around to inspect it from adb shell.
- // sleep(100000);
-
- // 0 -> successfully wrote the TraceProto out to file.
- // 1 -> failed along the way (#on_error and also see the error logs).
- return return_code;
-}
-
-#endif