diff options
Diffstat (limited to 'src/perfetto/main.cc')
-rw-r--r-- | src/perfetto/main.cc | 244 |
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 |