diff options
author | Fabien Sanglard <sanglardf@google.com> | 2019-02-21 15:13:29 -0800 |
---|---|---|
committer | Fabien Sanglard <sanglardf@google.com> | 2019-03-05 15:09:27 -0800 |
commit | 2d34e76daceaac41a8c578d7fa02aca864019dbb (patch) | |
tree | bd46b9065635728d88f2a6f40236c442ecad5f12 | |
parent | 63ebfcba5d62de4db9cfeb627ac98a4bc65ef425 (diff) |
Add --trace_folder to aapt2
Add a tracing API and instrument key functions in order to profile
aapt2 bottleneck. The API allows to generate systrace fragment files.
Impact on performance is neglibible with each Trace requiring less
than 1us and the final Flush operation at the end of a command
requiring around 40us.
Bug: None
Test: None
Change-Id: I51b564d3694e9384679f43b878b32295527dddf6
29 files changed, 311 insertions, 1 deletions
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index bc3a9a1c88c8..8bef221fe5ed 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -141,6 +141,7 @@ cc_library_host_static { "ResourceValues.cpp", "SdkConstants.cpp", "StringPool.cpp", + "trace/TraceBuffer.cpp", "xml/XmlActionExecutor.cpp", "xml/XmlDom.cpp", "xml/XmlPullParser.cpp", diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp index adf85b0ea8e8..39eb9879f86d 100644 --- a/tools/aapt2/Main.cpp +++ b/tools/aapt2/Main.cpp @@ -37,6 +37,7 @@ #include "cmd/Link.h" #include "cmd/Optimize.h" #include "io/FileStream.h" +#include "trace/TraceBuffer.h" #include "util/Files.h" #include "util/Util.h" @@ -107,9 +108,12 @@ class DaemonCommand : public Command { : Command("daemon", "m"), out_(out), diagnostics_(diagnostics) { SetDescription("Runs aapt in daemon mode. Each subsequent line is a single parameter to the\n" "command. The end of an invocation is signaled by providing an empty line."); + AddOptionalFlag("--trace_folder", "Generate systrace json trace fragment to specified folder.", + &trace_folder_); } - int Action(const std::vector<std::string>& /* args */) override { + int Action(const std::vector<std::string>& arguments) override { + TRACE_FLUSH_ARGS(trace_folder_ ? trace_folder_.value() : "", "daemon", arguments); text::Printer printer(out_); std::cout << "Ready" << std::endl; @@ -150,6 +154,7 @@ class DaemonCommand : public Command { private: io::FileOutputStream* out_; IDiagnostics* diagnostics_; + Maybe<std::string> trace_folder_; }; } // namespace aapt diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index dbd0a0ca1799..7c0619f33851 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -30,6 +30,7 @@ #include "NameMangler.h" #include "ResourceValues.h" #include "ValueVisitor.h" +#include "trace/TraceBuffer.h" #include "text/Unicode.h" #include "util/Util.h" @@ -79,6 +80,7 @@ ResourceTablePackage* ResourceTable::FindPackageById(uint8_t id) const { } ResourceTablePackage* ResourceTable::CreatePackage(const StringPiece& name, Maybe<uint8_t> id) { + TRACE_CALL(); ResourceTablePackage* package = FindOrCreatePackage(name); if (id && !package->id) { package->id = id; diff --git a/tools/aapt2/cmd/Command.cpp b/tools/aapt2/cmd/Command.cpp index 4424a357c1dd..919b4c98fa8f 100644 --- a/tools/aapt2/cmd/Command.cpp +++ b/tools/aapt2/cmd/Command.cpp @@ -25,6 +25,7 @@ #include "android-base/utf8.h" #include "androidfw/StringPiece.h" +#include "trace/TraceBuffer.h" #include "util/Util.h" using android::base::StringPrintf; @@ -178,6 +179,7 @@ void Command::Usage(std::ostream* out) { } int Command::Execute(const std::vector<StringPiece>& args, std::ostream* out_error) { + TRACE_NAME_ARGS("Command::Execute", args); std::vector<std::string> file_args; for (size_t i = 0; i < args.size(); i++) { diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index bec6c6973613..42dc74c6db55 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -45,6 +45,7 @@ #include "io/StringStream.h" #include "io/Util.h" #include "io/ZipArchive.h" +#include "trace/TraceBuffer.h" #include "util/Files.h" #include "util/Maybe.h" #include "util/Util.h" @@ -141,6 +142,7 @@ static std::string BuildIntermediateContainerFilename(const ResourcePathData& da static bool CompileTable(IAaptContext* context, const CompileOptions& options, const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer, const std::string& output_path) { + TRACE_CALL(); ResourceTable table; { auto fin = file->OpenInputStream(); @@ -286,6 +288,7 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options, static bool WriteHeaderAndDataToWriter(const StringPiece& output_path, const ResourceFile& file, io::KnownSizeInputStream* in, IArchiveWriter* writer, IDiagnostics* diag) { + TRACE_CALL(); // Start the entry so we can write the header. if (!writer->StartEntry(output_path, 0)) { diag->Error(DiagMessage(output_path) << "failed to open file"); @@ -352,6 +355,7 @@ static bool IsValidFile(IAaptContext* context, const std::string& input_path) { static bool CompileXml(IAaptContext* context, const CompileOptions& options, const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer, const std::string& output_path) { + TRACE_CALL(); if (context->IsVerbose()) { context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling XML"); } @@ -451,6 +455,7 @@ static bool CompileXml(IAaptContext* context, const CompileOptions& options, static bool CompilePng(IAaptContext* context, const CompileOptions& options, const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer, const std::string& output_path) { + TRACE_CALL(); if (context->IsVerbose()) { context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling PNG"); } @@ -558,6 +563,7 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options, static bool CompileFile(IAaptContext* context, const CompileOptions& options, const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer, const std::string& output_path) { + TRACE_CALL(); if (context->IsVerbose()) { context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling file"); } @@ -632,6 +638,7 @@ class CompileContext : public IAaptContext { int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer, CompileOptions& options) { + TRACE_CALL(); bool error = false; // Iterate over the input files in a stable, platform-independent manner @@ -707,6 +714,7 @@ int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* } int CompileCommand::Action(const std::vector<std::string>& args) { + TRACE_FLUSH(trace_folder_? trace_folder_.value() : "", "CompileCommand::Action"); CompileContext context(diagnostic_); context.SetVerbose(options_.verbose); diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h index 9b32cb3750a5..d3456b25da9a 100644 --- a/tools/aapt2/cmd/Compile.h +++ b/tools/aapt2/cmd/Compile.h @@ -60,6 +60,8 @@ class CompileCommand : public Command { "Sets the visibility of the compiled resources to the specified\n" "level. Accepted levels: public, private, default", &visibility_); AddOptionalSwitch("-v", "Enables verbose logging", &options_.verbose); + AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.", + &trace_folder_); } int Action(const std::vector<std::string>& args) override; @@ -68,6 +70,7 @@ class CompileCommand : public Command { IDiagnostics* diagnostic_; CompileOptions options_; Maybe<std::string> visibility_; + Maybe<std::string> trace_folder_; }; int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer, diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index a7b8d2535e79..f354bb610224 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -67,6 +67,7 @@ #include "process/IResourceTableConsumer.h" #include "process/SymbolTable.h" #include "split/TableSplitter.h" +#include "trace/TraceBuffer.h" #include "util/Files.h" #include "xml/XmlDom.h" @@ -213,6 +214,7 @@ class FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate { static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res, const StringPiece& path, bool keep_raw_values, bool utf16, OutputFormat format, IArchiveWriter* writer) { + TRACE_CALL(); if (context->IsVerbose()) { context->GetDiagnostics()->Note(DiagMessage(path) << "writing to archive (keep_raw_values=" << (keep_raw_values ? "true" : "false") @@ -250,6 +252,7 @@ static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res, // Inflates an XML file from the source path. static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) { + TRACE_CALL(); FileInputStream fin(path); if (fin.HadError()) { diag->Error(DiagMessage(path) << "failed to load XML file: " << fin.GetError()); @@ -421,6 +424,7 @@ std::vector<T> make_singleton_vec(T&& val) { std::vector<std::unique_ptr<xml::XmlResource>> ResourceFileFlattener::LinkAndVersionXmlFile( ResourceTable* table, FileOperation* file_op) { + TRACE_CALL(); xml::XmlResource* doc = file_op->xml_to_flatten.get(); const Source& src = doc->file.source; @@ -489,6 +493,7 @@ static auto kDrawableVersions = std::map<std::string, ApiVersion>{ }; bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) { + TRACE_CALL(); bool error = false; std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files; @@ -806,6 +811,7 @@ class Linker { // Creates a SymbolTable that loads symbols from the various APKs. // Pre-condition: context_->GetCompilationPackage() needs to be set. bool LoadSymbolsFromIncludePaths() { + TRACE_NAME("LoadSymbolsFromIncludePaths: #" + std::to_string(options_.include_paths.size())); auto asset_source = util::make_unique<AssetManagerSymbolSource>(); for (const std::string& path : options_.include_paths) { if (context_->IsVerbose()) { @@ -891,6 +897,7 @@ class Linker { } Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res, IDiagnostics* diag) { + TRACE_CALL(); // Make sure the first element is <manifest> with package attribute. xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get()); if (manifest_el == nullptr) { @@ -1041,6 +1048,7 @@ class Linker { } bool FlattenTable(ResourceTable* table, OutputFormat format, IArchiveWriter* writer) { + TRACE_CALL(); switch (format) { case OutputFormat::kApk: { BigBuffer buffer(1024); @@ -1114,6 +1122,7 @@ class Linker { } bool GenerateJavaClasses() { + TRACE_CALL(); // The set of packages whose R class to call in the main classes onResourcesLoaded callback. std::vector<std::string> packages_to_callback; @@ -1197,6 +1206,7 @@ class Linker { } bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) { + TRACE_CALL(); if (!options_.generate_java_class_path) { return true; } @@ -1254,6 +1264,7 @@ class Linker { } bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) { + TRACE_CALL(); if (!out) { return true; } @@ -1278,6 +1289,7 @@ class Linker { } bool MergeStaticLibrary(const std::string& input, bool override) { + TRACE_CALL(); if (context_->IsVerbose()) { context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input); } @@ -1328,6 +1340,7 @@ class Linker { bool MergeExportedSymbols(const Source& source, const std::vector<SourcedResourceName>& exported_symbols) { + TRACE_CALL(); // Add the exports of this file to the table. for (const SourcedResourceName& exported_symbol : exported_symbols) { ResourceName res_name = exported_symbol.name; @@ -1353,6 +1366,7 @@ class Linker { } bool MergeCompiledFile(const ResourceFile& compiled_file, io::IFile* file, bool override) { + TRACE_CALL(); if (context_->IsVerbose()) { context_->GetDiagnostics()->Note(DiagMessage() << "merging '" << compiled_file.name @@ -1371,6 +1385,7 @@ class Linker { // An io::IFileCollection is created from the ZIP file and added to the set of // io::IFileCollections that are open. bool MergeArchive(const std::string& input, bool override) { + TRACE_CALL(); if (context_->IsVerbose()) { context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input); } @@ -1418,6 +1433,7 @@ class Linker { // All other file types are ignored. This is because these files could be coming from a zip, // where we could have other files like classes.dex. bool MergeFile(io::IFile* file, bool override) { + TRACE_CALL(); const Source& src = file->GetSource(); if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) { @@ -1458,6 +1474,7 @@ class Linker { while ((entry = reader.Next()) != nullptr) { if (entry->Type() == ContainerEntryType::kResTable) { + TRACE_NAME(std::string("Process ResTable:") + file->GetSource().path); pb::ResourceTable pb_table; if (!entry->GetResTable(&pb_table)) { context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read resource table: " @@ -1478,6 +1495,7 @@ class Linker { return false; } } else if (entry->Type() == ContainerEntryType::kResFile) { + TRACE_NAME(std::string("Process ResFile") + file->GetSource().path); pb::internal::CompiledFile pb_compiled_file; off64_t offset; size_t len; @@ -1551,6 +1569,7 @@ class Linker { // to the IArchiveWriter. bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest, ResourceTable* table) { + TRACE_CALL(); const bool keep_raw_values = (context_->GetPackageType() == PackageType::kStaticLib) || options_.keep_raw_values; bool result = FlattenXml(context_, *manifest, kAndroidManifestPath, keep_raw_values, @@ -1632,6 +1651,7 @@ class Linker { } int Run(const std::vector<std::string>& input_files) { + TRACE_CALL(); // Load the AndroidManifest.xml std::unique_ptr<xml::XmlResource> manifest_xml = LoadXml(options_.manifest_path, context_->GetDiagnostics()); @@ -1839,6 +1859,7 @@ class Linker { std::vector<ConfigDescription> excluded_configs; for (auto& config_string : options_.exclude_configs_) { + TRACE_NAME("ConfigDescription::Parse"); ConfigDescription config_description; if (!ConfigDescription::Parse(config_string, &config_description)) { @@ -2038,6 +2059,7 @@ class Linker { }; int LinkCommand::Action(const std::vector<std::string>& args) { + TRACE_FLUSH(trace_folder_ ? trace_folder_.value() : "", "LinkCommand::Action"); LinkContext context(diag_); // Expand all argument-files passed into the command line. These start with '@'. diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 1fc149ab41af..7c583858ee1d 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -25,6 +25,7 @@ #include "split/TableSplitter.h" #include "format/binary/TableFlattener.h" #include "link/ManifestFixer.h" +#include "trace/TraceBuffer.h" namespace aapt { @@ -277,6 +278,8 @@ class LinkCommand : public Command { "Do not allow overlays with different visibility levels.", &options_.strict_visibility); AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_); + AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.", + &trace_folder_); } int Action(const std::vector<std::string>& args) override; @@ -300,6 +303,7 @@ class LinkCommand : public Command { bool proto_format_ = false; Maybe<std::string> stable_id_file_path_; std::vector<std::string> split_args_; + Maybe<std::string> trace_folder_; }; }// namespace aapt diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp index 33122dccb7de..d396d81d699a 100644 --- a/tools/aapt2/compile/Png.cpp +++ b/tools/aapt2/compile/Png.cpp @@ -27,6 +27,7 @@ #include "androidfw/ResourceTypes.h" #include "Source.h" +#include "trace/TraceBuffer.h" #include "util/BigBuffer.h" #include "util/Util.h" @@ -1233,6 +1234,7 @@ getout: bool Png::process(const Source& source, std::istream* input, BigBuffer* outBuffer, const PngOptions& options) { + TRACE_CALL(); png_byte signature[kPngSignatureSize]; // Read the PNG signature first. diff --git a/tools/aapt2/compile/PngCrunch.cpp b/tools/aapt2/compile/PngCrunch.cpp index 0346a1982d8a..1f4ea44d9f86 100644 --- a/tools/aapt2/compile/PngCrunch.cpp +++ b/tools/aapt2/compile/PngCrunch.cpp @@ -27,6 +27,8 @@ #include "android-base/logging.h" #include "android-base/macros.h" +#include "trace/TraceBuffer.h" + namespace aapt { // Custom deleter that destroys libpng read and info structs. @@ -142,6 +144,7 @@ static void WriteDataToStream(png_structp png_ptr, png_bytep buffer, png_size_t } std::unique_ptr<Image> ReadPng(IAaptContext* context, const Source& source, io::InputStream* in) { + TRACE_CALL(); // Create a diagnostics that has the source information encoded. SourcePathDiagnostics source_diag(source, context->GetDiagnostics()); @@ -480,6 +483,7 @@ static void WriteNinePatch(png_structp write_ptr, png_infop write_info_ptr, bool WritePng(IAaptContext* context, const Image* image, const NinePatch* nine_patch, io::OutputStream* out, const PngOptions& options) { + TRACE_CALL(); // Create and initialize the write png_struct with the default error and // warning handlers. // The header version is also passed in to ensure that this was built against the same diff --git a/tools/aapt2/compile/XmlIdCollector.cpp b/tools/aapt2/compile/XmlIdCollector.cpp index 2199d003bccb..50541152f802 100644 --- a/tools/aapt2/compile/XmlIdCollector.cpp +++ b/tools/aapt2/compile/XmlIdCollector.cpp @@ -22,6 +22,7 @@ #include "ResourceUtils.h" #include "ResourceValues.h" #include "text/Unicode.h" +#include "trace/TraceBuffer.h" #include "xml/XmlDom.h" namespace aapt { @@ -72,6 +73,7 @@ struct IdCollector : public xml::Visitor { } // namespace bool XmlIdCollector::Consume(IAaptContext* context, xml::XmlResource* xmlRes) { + TRACE_CALL(); xmlRes->file.exported_symbols.clear(); SourcePathDiagnostics source_diag(xmlRes->file.source, context->GetDiagnostics()); IdCollector collector(&xmlRes->file.exported_symbols, &source_diag); diff --git a/tools/aapt2/format/Container.cpp b/tools/aapt2/format/Container.cpp index d4b45717e015..f1890488276c 100644 --- a/tools/aapt2/format/Container.cpp +++ b/tools/aapt2/format/Container.cpp @@ -19,6 +19,8 @@ #include "android-base/scopeguard.h" #include "android-base/stringprintf.h" +#include "trace/TraceBuffer.h" + using ::android::base::StringPrintf; using ::google::protobuf::io::CodedInputStream; using ::google::protobuf::io::CodedOutputStream; @@ -171,6 +173,7 @@ ContainerEntryType ContainerReaderEntry::Type() const { } bool ContainerReaderEntry::GetResTable(pb::ResourceTable* out_table) { + TRACE_CALL(); CHECK(type_ == ContainerEntryType::kResTable) << "reading a kResTable when the type is kResFile"; if (length_ > std::numeric_limits<int>::max()) { reader_->error_ = StringPrintf("entry length %zu is too large", length_); @@ -261,6 +264,7 @@ ContainerReader::ContainerReader(io::InputStream* in) total_entry_count_(0u), current_entry_count_(0u), entry_(this) { + TRACE_CALL(); ::google::protobuf::uint32 magic; if (!coded_in_.ReadLittleEndian32(&magic)) { std::ostringstream error; diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index d677317dc98d..aa578a2a6ff4 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -32,6 +32,7 @@ #include "ValueVisitor.h" #include "format/binary/ChunkWriter.h" #include "format/binary/ResourceTypeExtensions.h" +#include "trace/TraceBuffer.h" #include "util/BigBuffer.h" using namespace android; @@ -238,6 +239,7 @@ class PackageFlattener { } bool FlattenPackage(BigBuffer* buffer) { + TRACE_CALL(); ChunkWriter pkg_writer(buffer); ResTable_package* pkg_header = pkg_writer.StartChunk<ResTable_package>(RES_TABLE_PACKAGE_TYPE); pkg_header->id = util::HostToDevice32(package_->id.value()); @@ -710,6 +712,7 @@ class PackageFlattener { } // namespace bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) { + TRACE_CALL(); // We must do this before writing the resources, since the string pool IDs may change. table->string_pool.Prune(); table->string_pool.Sort([](const StringPool::Context& a, const StringPool::Context& b) -> int { diff --git a/tools/aapt2/io/Util.cpp b/tools/aapt2/io/Util.cpp index 97516322c4cb..ce6d9352180d 100644 --- a/tools/aapt2/io/Util.cpp +++ b/tools/aapt2/io/Util.cpp @@ -18,6 +18,8 @@ #include "google/protobuf/io/zero_copy_stream_impl_lite.h" +#include "trace/TraceBuffer.h" + using ::android::StringPiece; using ::google::protobuf::io::ZeroCopyOutputStream; @@ -26,6 +28,7 @@ namespace io { bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std::string& out_path, uint32_t compression_flags, IArchiveWriter* writer) { + TRACE_CALL(); if (context->IsVerbose()) { context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive"); } @@ -40,6 +43,7 @@ bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std: bool CopyFileToArchive(IAaptContext* context, io::IFile* file, const std::string& out_path, uint32_t compression_flags, IArchiveWriter* writer) { + TRACE_CALL(); std::unique_ptr<io::IData> data = file->OpenAsData(); if (!data) { context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file"); @@ -57,6 +61,7 @@ bool CopyFileToArchivePreserveCompression(IAaptContext* context, io::IFile* file bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg, const std::string& out_path, uint32_t compression_flags, IArchiveWriter* writer) { + TRACE_CALL(); if (context->IsVerbose()) { context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive"); } @@ -83,6 +88,7 @@ bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* } bool Copy(OutputStream* out, InputStream* in) { + TRACE_CALL(); const void* in_buffer; size_t in_len; while (in->Next(&in_buffer, &in_len)) { diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp index 427dc92505d4..f6aaa1280a61 100644 --- a/tools/aapt2/io/ZipArchive.cpp +++ b/tools/aapt2/io/ZipArchive.cpp @@ -20,6 +20,7 @@ #include "ziparchive/zip_archive.h" #include "Source.h" +#include "trace/TraceBuffer.h" #include "util/Files.h" #include "util/Util.h" @@ -93,6 +94,7 @@ ZipFileCollection::ZipFileCollection() : handle_(nullptr) {} std::unique_ptr<ZipFileCollection> ZipFileCollection::Create( const StringPiece& path, std::string* out_error) { + TRACE_CALL(); constexpr static const int32_t kEmptyArchive = -6; std::unique_ptr<ZipFileCollection> collection = diff --git a/tools/aapt2/link/AutoVersioner.cpp b/tools/aapt2/link/AutoVersioner.cpp index 960c7d46cc98..73b92542a755 100644 --- a/tools/aapt2/link/AutoVersioner.cpp +++ b/tools/aapt2/link/AutoVersioner.cpp @@ -23,6 +23,7 @@ #include "ResourceTable.h" #include "SdkConstants.h" #include "ValueVisitor.h" +#include "trace/TraceBuffer.h" using android::ConfigDescription; @@ -70,6 +71,7 @@ ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry, } bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) { + TRACE_NAME("AutoVersioner::Consume"); for (auto& package : table->packages) { for (auto& type : package->types) { if (type->type != ResourceType::kStyle) { diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 582a5b869c65..b0a2055cafc8 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -21,6 +21,7 @@ #include "android-base/logging.h" #include "ResourceUtils.h" +#include "trace/TraceBuffer.h" #include "util/Util.h" #include "xml/XmlActionExecutor.h" #include "xml/XmlDom.h" @@ -451,6 +452,7 @@ static bool RenameManifestPackage(const StringPiece& package_override, xml::Elem } bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) { + TRACE_CALL(); xml::Element* root = xml::FindRootElement(doc->root.get()); if (!root || !root->namespace_uri.empty() || root->name != "manifest") { context->GetDiagnostics()->Error(DiagMessage(doc->file.source) diff --git a/tools/aapt2/link/ProductFilter.cpp b/tools/aapt2/link/ProductFilter.cpp index c1a95ee1bcec..793740af3021 100644 --- a/tools/aapt2/link/ProductFilter.cpp +++ b/tools/aapt2/link/ProductFilter.cpp @@ -17,6 +17,7 @@ #include "link/Linkers.h" #include "ResourceTable.h" +#include "trace/TraceBuffer.h" namespace aapt { @@ -81,6 +82,7 @@ ProductFilter::ResourceConfigValueIter ProductFilter::SelectProductToKeep( } bool ProductFilter::Consume(IAaptContext* context, ResourceTable* table) { + TRACE_NAME("ProductFilter::Consume"); bool error = false; for (auto& pkg : table->packages) { for (auto& type : pkg->types) { diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp index c2340ba65e38..28f09aa48365 100644 --- a/tools/aapt2/link/ReferenceLinker.cpp +++ b/tools/aapt2/link/ReferenceLinker.cpp @@ -27,6 +27,7 @@ #include "link/Linkers.h" #include "process/IResourceTableConsumer.h" #include "process/SymbolTable.h" +#include "trace/TraceBuffer.h" #include "util/Util.h" #include "xml/XmlUtil.h" @@ -353,6 +354,7 @@ bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* referen } bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) { + TRACE_NAME("ReferenceLinker::Consume"); EmptyDeclStack decl_stack; bool error = false; for (auto& package : table->packages) { diff --git a/tools/aapt2/link/ResourceExcluder.cpp b/tools/aapt2/link/ResourceExcluder.cpp index 2555995dfc8e..b3b9dc47fd84 100644 --- a/tools/aapt2/link/ResourceExcluder.cpp +++ b/tools/aapt2/link/ResourceExcluder.cpp @@ -20,6 +20,7 @@ #include "DominatorTree.h" #include "ResourceTable.h" +#include "trace/TraceBuffer.h" using android::ConfigDescription; @@ -65,6 +66,7 @@ void RemoveIfExcluded(std::set<std::pair<ConfigDescription, int>>& excluded_conf } // namespace bool ResourceExcluder::Consume(IAaptContext* context, ResourceTable* table) { + TRACE_NAME("ResourceExcluder::Consume"); for (auto& package : table->packages) { for (auto& type : package->types) { for (auto& entry : type->entries) { diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index cc9fed554350..e9375176f26b 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -21,6 +21,7 @@ #include "ResourceTable.h" #include "ResourceUtils.h" #include "ResourceValues.h" +#include "trace/TraceBuffer.h" #include "ValueVisitor.h" #include "util/Util.h" @@ -38,6 +39,7 @@ TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table, } bool TableMerger::Merge(const Source& src, ResourceTable* table, bool overlay) { + TRACE_CALL(); // We allow adding new resources if this is not an overlay, or if the options allow overlays // to add new resources. return MergeImpl(src, table, overlay, options_.auto_add_overlay || !overlay /*allow_new*/); diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp index 160ff925f6cc..d68f7dd44c9f 100644 --- a/tools/aapt2/link/XmlReferenceLinker.cpp +++ b/tools/aapt2/link/XmlReferenceLinker.cpp @@ -25,6 +25,7 @@ #include "link/ReferenceLinker.h" #include "process/IResourceTableConsumer.h" #include "process/SymbolTable.h" +#include "trace/TraceBuffer.h" #include "util/Util.h" #include "xml/XmlDom.h" @@ -151,6 +152,7 @@ class XmlVisitor : public xml::PackageAwareVisitor { } // namespace bool XmlReferenceLinker::Consume(IAaptContext* context, xml::XmlResource* resource) { + TRACE_NAME("XmlReferenceLinker::Consume"); CallSite callsite{resource->file.name.package}; std::string out_name = resource->file.name.entry; diff --git a/tools/aapt2/optimize/ResourceDeduper.cpp b/tools/aapt2/optimize/ResourceDeduper.cpp index ee2dfbce7c06..78ebcb97b811 100644 --- a/tools/aapt2/optimize/ResourceDeduper.cpp +++ b/tools/aapt2/optimize/ResourceDeduper.cpp @@ -20,6 +20,7 @@ #include "DominatorTree.h" #include "ResourceTable.h" +#include "trace/TraceBuffer.h" using android::ConfigDescription; @@ -110,6 +111,7 @@ static void DedupeEntry(IAaptContext* context, ResourceEntry* entry) { } // namespace bool ResourceDeduper::Consume(IAaptContext* context, ResourceTable* table) { + TRACE_CALL(); for (auto& package : table->packages) { for (auto& type : package->types) { for (auto& entry : type->entries) { diff --git a/tools/aapt2/optimize/VersionCollapser.cpp b/tools/aapt2/optimize/VersionCollapser.cpp index f9856047ac40..cd791bda250b 100644 --- a/tools/aapt2/optimize/VersionCollapser.cpp +++ b/tools/aapt2/optimize/VersionCollapser.cpp @@ -20,6 +20,7 @@ #include <vector> #include "ResourceTable.h" +#include "trace/TraceBuffer.h" using android::ConfigDescription; @@ -144,6 +145,7 @@ static void CollapseVersions(int min_sdk, ResourceEntry* entry) { } bool VersionCollapser::Consume(IAaptContext* context, ResourceTable* table) { + TRACE_NAME("VersionCollapser::Consume"); const int min_sdk = context->GetMinSdkVersion(); for (auto& package : table->packages) { for (auto& type : package->types) { diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp index 78e00746f6cb..61a8fbbb7f52 100644 --- a/tools/aapt2/process/SymbolTable.cpp +++ b/tools/aapt2/process/SymbolTable.cpp @@ -30,6 +30,7 @@ #include "Resource.h" #include "ResourceUtils.h" #include "ValueVisitor.h" +#include "trace/TraceBuffer.h" #include "util/Util.h" using ::android::ApkAssets; @@ -217,6 +218,7 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName( } bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) { + TRACE_CALL(); if (std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path.data())) { apk_assets_.push_back(std::move(apk)); @@ -233,6 +235,7 @@ bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) { } std::map<size_t, std::string> AssetManagerSymbolSource::GetAssignedPackageIds() const { + TRACE_CALL(); std::map<size_t, std::string> package_map; asset_manager_.ForEachPackage([&package_map](const std::string& name, uint8_t id) -> bool { package_map.insert(std::make_pair(id, name)); diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp index 24cd5ba302ea..6a672717f38e 100644 --- a/tools/aapt2/split/TableSplitter.cpp +++ b/tools/aapt2/split/TableSplitter.cpp @@ -27,6 +27,7 @@ #include "androidfw/ConfigDescription.h" #include "ResourceTable.h" +#include "trace/TraceBuffer.h" #include "util/Util.h" using ::android::ConfigDescription; @@ -154,6 +155,7 @@ static void MarkNonPreferredDensitiesAsClaimed( } } bool TableSplitter::VerifySplitConstraints(IAaptContext* context) { + TRACE_CALL(); bool error = false; for (size_t i = 0; i < split_constraints_.size(); i++) { if (split_constraints_[i].configs.size() == 0) { diff --git a/tools/aapt2/trace/TraceBuffer.cpp b/tools/aapt2/trace/TraceBuffer.cpp new file mode 100644 index 000000000000..b4b31d9daf6e --- /dev/null +++ b/tools/aapt2/trace/TraceBuffer.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2019 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 "TraceBuffer.h" + +#include <chrono> +#include <sstream> +#include <unistd.h> +#include <vector> + +#include <inttypes.h> + +#include "android-base/utf8.h" + +#include "util/Files.h" + +namespace aapt { +namespace tracebuffer { + +namespace { + +constexpr char kBegin = 'B'; +constexpr char kEnd = 'E'; + +struct TracePoint { + pid_t tid; + int64_t time; + std::string tag; + char type; +}; + +std::vector<TracePoint> traces; + +int64_t GetTime() noexcept { + auto now = std::chrono::steady_clock::now(); + return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count(); +} + +} // namespace anonymous + +void AddWithTime(const std::string& tag, char type, int64_t time) noexcept { + TracePoint t = {getpid(), time, tag, type}; + traces.emplace_back(t); +} + +void Add(const std::string& tag, char type) noexcept { + AddWithTime(tag, type, GetTime()); +} + + + + +void Flush(const std::string& basePath) { + TRACE_CALL(); + if (basePath.empty()) { + return; + } + + std::stringstream s; + s << basePath << aapt::file::sDirSep << "report_aapt2_" << getpid() << ".json"; + FILE* f = android::base::utf8::fopen(s.str().c_str(), "a"); + if (f == nullptr) { + return; + } + + for(const TracePoint& trace : traces) { + fprintf(f, "{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", " + "\"name\" : \"%s\" },\n", trace.time, trace.type, 0, trace.tid, trace.tag.c_str()); + } + fclose(f); + traces.clear(); +} + +} // namespace tracebuffer + +void BeginTrace(const std::string& tag) { + tracebuffer::Add(tag, tracebuffer::kBegin); +} + +void EndTrace() { + tracebuffer::Add("", tracebuffer::kEnd); +} + +Trace::Trace(const std::string& tag) { + tracebuffer::Add(tag, tracebuffer::kBegin); +} + +Trace::Trace(const std::string& tag, const std::vector<android::StringPiece>& args) { + std::stringstream s; + s << tag; + s << " "; + for (auto& arg : args) { + s << arg.to_string(); + s << " "; + } + tracebuffer::Add(s.str(), tracebuffer::kBegin); +} + +Trace::~Trace() { + tracebuffer::Add("", tracebuffer::kEnd); +} + +FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag) + : basepath_(basepath) { + tracebuffer::Add(tag, tracebuffer::kBegin); +} + +FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag, + const std::vector<android::StringPiece>& args) : basepath_(basepath) { + std::stringstream s; + s << tag; + s << " "; + for (auto& arg : args) { + s << arg.to_string(); + s << " "; + } + tracebuffer::Add(s.str(), tracebuffer::kBegin); +} + +FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag, + const std::vector<std::string>& args) : basepath_(basepath){ + std::stringstream s; + s << tag; + s << " "; + for (auto& arg : args) { + s << arg; + s << " "; + } + tracebuffer::Add(s.str(), tracebuffer::kBegin); +} + +FlushTrace::~FlushTrace() { + tracebuffer::Add("", tracebuffer::kEnd); + tracebuffer::Flush(basepath_); +} + +} // namespace aapt + diff --git a/tools/aapt2/trace/TraceBuffer.h b/tools/aapt2/trace/TraceBuffer.h new file mode 100644 index 000000000000..8618e0eeb731 --- /dev/null +++ b/tools/aapt2/trace/TraceBuffer.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 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. + */ + +#ifndef AAPT_TRACEBUFFER_H +#define AAPT_TRACEBUFFER_H + +#include <string> +#include <vector> + +#include <androidfw/StringPiece.h> + +namespace aapt { + +// Record timestamps for beginning and end of a task and generate systrace json fragments. +// This is an in-process ftrace which has the advantage of being platform independent. +// These methods are NOT thread-safe since aapt2 is not multi-threaded. + +// Convenience RIAA object to automatically finish an event when object goes out of scope. +class Trace { +public: + Trace(const std::string& tag); + Trace(const std::string& tag, const std::vector<android::StringPiece>& args); + ~Trace(); +}; + +// Manual markers. +void BeginTrace(const std::string& tag); +void EndTrace(); + +// A master trace is required to flush events to disk. Events are formatted in systrace +// json format. +class FlushTrace { +public: + explicit FlushTrace(const std::string& basepath, const std::string& tag); + explicit FlushTrace(const std::string& basepath, const std::string& tag, + const std::vector<android::StringPiece>& args); + explicit FlushTrace(const std::string& basepath, const std::string& tag, + const std::vector<std::string>& args); + ~FlushTrace(); +private: + std::string basepath_; +}; + +#define TRACE_CALL() Trace __t(__func__) +#define TRACE_NAME(tag) Trace __t(tag) +#define TRACE_NAME_ARGS(tag, args) Trace __t(tag, args) + +#define TRACE_FLUSH(basename, tag) FlushTrace __t(basename, tag) +#define TRACE_FLUSH_ARGS(basename, tag, args) FlushTrace __t(basename, tag, args) +} // namespace aapt +#endif //AAPT_TRACEBUFFER_H diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp index acd07c2876c8..9a725fad8727 100644 --- a/tools/aapt2/xml/XmlDom.cpp +++ b/tools/aapt2/xml/XmlDom.cpp @@ -26,6 +26,7 @@ #include "android-base/logging.h" #include "ResourceUtils.h" +#include "trace/TraceBuffer.h" #include "XmlPullParser.h" #include "util/Util.h" @@ -264,6 +265,7 @@ static void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPoo } std::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* out_error) { + TRACE_CALL(); // We import the android namespace because on Windows NO_ERROR is a macro, not // an enum, which causes errors when qualifying it with android:: using namespace android; |