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
This commit is contained in:
Fabien Sanglard
2019-02-21 15:13:29 -08:00
parent 63ebfcba5d
commit 2d34e76dac
29 changed files with 311 additions and 1 deletions

View File

@@ -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",

View File

@@ -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

View File

@@ -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;

View File

@@ -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++) {

View File

@@ -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);

View File

@@ -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,

View File

@@ -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 '@'.

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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)) {

View File

@@ -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 =

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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*/);

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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));

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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;