Add more timing to FileWriter
Bug: b/422947619
Change-Id: Ie948b1d7898a7c9b8cb007db9c956ee8dad72086
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 72db23e..bb8d845 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -897,7 +897,7 @@
// Collect the non-fixed sections.
timing.time("collect", fileWriter::collect);
// Generate and write the bytes.
- return timing.time("generate", () -> fileWriter.generate());
+ return timing.time("generate", () -> fileWriter.generate(timing));
}
private static String mapMainDexListName(DexType type, NamingLens namingLens) {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriterContainer.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriterContainer.java
index e60883b..cce512c 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriterContainer.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriterContainer.java
@@ -259,6 +259,6 @@
// Collect the non-fixed sections.
timing.time("collect", fileWriter::collect);
// Generate and write the bytes.
- return timing.time("generate", () -> fileWriter.generate(offset, CONTAINER_DEX));
+ return timing.time("generate", () -> fileWriter.generate(timing, offset, CONTAINER_DEX));
}
}
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 38138bb..7cdd5cc 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -57,6 +57,7 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.LebUtils;
+import com.android.tools.r8.utils.timing.Timing;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
@@ -200,12 +201,12 @@
}
}
- public ByteBufferResult generate() {
- DexContainerSection res = generate(0, SINGLE_DEX);
+ public ByteBufferResult generate(Timing timing) {
+ DexContainerSection res = generate(timing, 0, SINGLE_DEX);
return new ByteBufferResult(res.getBuffer().stealByteBuffer(), res.getLayout().getEndOfFile());
}
- public DexContainerSection generate(int offset, DexVersion.Layout layoutType) {
+ public DexContainerSection generate(Timing timing, int offset, DexVersion.Layout layoutType) {
// Check restrictions on interface methods.
checkInterfaceMethods();
@@ -213,119 +214,127 @@
assert verifyNames();
Layout layout = Layout.from(mapping, offset, layoutType, includeStringData);
- layout.setCodesOffset(layout.dataSectionOffset);
+ MixedSectionLayoutStrategy mixedSectionLayoutStrategy = null;
+ try (Timing t0 = timing.begin("Write codes")) {
+ layout.setCodesOffset(layout.dataSectionOffset);
- // Sort the codes first, as their order might impact size due to alignment constraints.
- MixedSectionLayoutStrategy mixedSectionLayoutStrategy =
- MixedSectionLayoutStrategy.create(appView, mixedSectionOffsets, virtualFile);
- Collection<ProgramMethod> codes = mixedSectionLayoutStrategy.getCodeLayout();
+ // Sort the codes first, as their order might impact size due to alignment constraints.
+ mixedSectionLayoutStrategy =
+ MixedSectionLayoutStrategy.create(appView, mixedSectionOffsets, virtualFile);
+ Collection<ProgramMethod> codes = mixedSectionLayoutStrategy.getCodeLayout();
- // Output the debug_info_items first, as they have no dependencies.
- SizeAndCount sizeAndCountOfCodeItems = sizeAndCountOfCodeItems(codes);
- dest.moveTo(layout.getCodesOffset() + sizeAndCountOfCodeItems.size);
- if (mixedSectionOffsets.getDebugInfos().isEmpty()) {
- layout.setDebugInfosOffset(0);
- } else {
- // Ensure deterministic ordering of debug info by sorting consistent with the code objects.
- layout.setDebugInfosOffset(dest.align(1));
- Set<DexDebugInfoForWriting> seen = new HashSet<>(mixedSectionOffsets.getDebugInfos().size());
- for (ProgramMethod method : codes) {
- DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
- DexDebugInfoForWriting info = code.getDebugInfoForWriting();
- if (info != null && seen.add(info)) {
- writeDebugItem(code, info);
- }
- }
- }
-
- // Remember the typelist offset for later.
- layout.setTypeListsOffset(dest.align(4)); // type_list are aligned.
-
- // Now output the code.
- dest.moveTo(layout.getCodesOffset());
- assert dest.isAligned(4);
- Map<DexWritableCacheKey, Integer> offsetCache = new HashMap<>();
- for (ProgramMethod method : codes) {
- DexWritableCode dexWritableCode = method.getDefinition().getCode().asDexWritableCode();
- if (!options.canUseCanonicalizedCodeObjects()) {
- writeCodeItem(method, dexWritableCode);
+ // Output the debug_info_items first, as they have no dependencies.
+ SizeAndCount sizeAndCountOfCodeItems = sizeAndCountOfCodeItems(codes);
+ dest.moveTo(layout.getCodesOffset() + sizeAndCountOfCodeItems.size);
+ if (mixedSectionOffsets.getDebugInfos().isEmpty()) {
+ layout.setDebugInfosOffset(0);
} else {
- DexWritableCacheKey cacheLookupKey =
- dexWritableCode.getCacheLookupKey(method, appView.dexItemFactory());
- Integer offsetOrNull = offsetCache.get(cacheLookupKey);
- if (offsetOrNull != null) {
- mixedSectionOffsets.setOffsetFor(method.getDefinition(), offsetOrNull);
- } else {
- offsetCache.put(cacheLookupKey, writeCodeItem(method, dexWritableCode));
+ // Ensure deterministic ordering of debug info by sorting consistent with the code objects.
+ layout.setDebugInfosOffset(dest.align(1));
+ Set<DexDebugInfoForWriting> seen =
+ new HashSet<>(mixedSectionOffsets.getDebugInfos().size());
+ for (ProgramMethod method : codes) {
+ DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
+ DexDebugInfoForWriting info = code.getDebugInfoForWriting();
+ if (info != null && seen.add(info)) {
+ writeDebugItem(code, info);
+ }
}
}
+
+ // Remember the typelist offset for later.
+ layout.setTypeListsOffset(dest.align(4)); // type_list are aligned.
+
+ // Now output the code.
+ dest.moveTo(layout.getCodesOffset());
+ assert dest.isAligned(4);
+ Map<DexWritableCacheKey, Integer> offsetCache = new HashMap<>();
+ for (ProgramMethod method : codes) {
+ DexWritableCode dexWritableCode = method.getDefinition().getCode().asDexWritableCode();
+ if (!options.canUseCanonicalizedCodeObjects()) {
+ writeCodeItem(method, dexWritableCode);
+ } else {
+ DexWritableCacheKey cacheLookupKey =
+ dexWritableCode.getCacheLookupKey(method, appView.dexItemFactory());
+ Integer offsetOrNull = offsetCache.get(cacheLookupKey);
+ if (offsetOrNull != null) {
+ mixedSectionOffsets.setOffsetFor(method.getDefinition(), offsetOrNull);
+ } else {
+ offsetCache.put(cacheLookupKey, writeCodeItem(method, dexWritableCode));
+ }
+ }
+ }
+ assert sizeAndCountOfCodeItems.getCount()
+ == ImmutableSet.copyOf(mixedSectionOffsets.codes.values()).size();
+ layout.setCodeCount(sizeAndCountOfCodeItems.getCount());
+ assert layout.getDebugInfosOffset() == 0 || dest.position() == layout.getDebugInfosOffset();
}
- assert sizeAndCountOfCodeItems.getCount()
- == ImmutableSet.copyOf(mixedSectionOffsets.codes.values()).size();
- layout.setCodeCount(sizeAndCountOfCodeItems.getCount());
- assert layout.getDebugInfosOffset() == 0 || dest.position() == layout.getDebugInfosOffset();
// Now the type lists and rest.
- dest.moveTo(layout.getTypeListsOffset());
- writeItems(
- mixedSectionLayoutStrategy.getTypeListLayout(),
- layout::alreadySetOffset,
- this::writeTypeList);
- if (includeStringData) {
+ try (Timing t0 = timing.begin("Write remaining mixed sections")) {
+ dest.moveTo(layout.getTypeListsOffset());
writeItems(
- mixedSectionLayoutStrategy.getStringDataLayout(),
- layout::setStringDataOffsets,
- this::writeStringData);
- } else {
- layout.stringDataOffsets = 0; // Empty string data section.
- }
- writeItems(
- mixedSectionLayoutStrategy.getAnnotationLayout(),
- layout::setAnnotationsOffset,
- this::writeAnnotation);
- writeItems(
- mixedSectionLayoutStrategy.getClassDataLayout(),
- layout::setClassDataOffset,
- this::writeClassData);
- writeItems(
- mixedSectionLayoutStrategy.getEncodedArrayLayout(),
- layout::setEncodedArraysOffset,
- this::writeEncodedArray);
- writeItems(
- mixedSectionLayoutStrategy.getAnnotationSetLayout(),
- layout::setAnnotationSetsOffset,
- this::writeAnnotationSet,
- 4);
- writeItems(
- mixedSectionLayoutStrategy.getAnnotationSetRefListLayout(),
- layout::setAnnotationSetRefListsOffset,
- this::writeAnnotationSetRefList,
- 4);
- writeItems(
- mixedSectionLayoutStrategy.getAnnotationDirectoryLayout(),
- layout::setAnnotationDirectoriesOffset,
- this::writeAnnotationDirectory,
- 4);
+ mixedSectionLayoutStrategy.getTypeListLayout(),
+ layout::alreadySetOffset,
+ this::writeTypeList);
+ if (includeStringData) {
+ writeItems(
+ mixedSectionLayoutStrategy.getStringDataLayout(),
+ layout::setStringDataOffsets,
+ this::writeStringData);
+ } else {
+ layout.stringDataOffsets = 0; // Empty string data section.
+ }
+ writeItems(
+ mixedSectionLayoutStrategy.getAnnotationLayout(),
+ layout::setAnnotationsOffset,
+ this::writeAnnotation);
+ writeItems(
+ mixedSectionLayoutStrategy.getClassDataLayout(),
+ layout::setClassDataOffset,
+ this::writeClassData);
+ writeItems(
+ mixedSectionLayoutStrategy.getEncodedArrayLayout(),
+ layout::setEncodedArraysOffset,
+ this::writeEncodedArray);
+ writeItems(
+ mixedSectionLayoutStrategy.getAnnotationSetLayout(),
+ layout::setAnnotationSetsOffset,
+ this::writeAnnotationSet,
+ 4);
+ writeItems(
+ mixedSectionLayoutStrategy.getAnnotationSetRefListLayout(),
+ layout::setAnnotationSetRefListsOffset,
+ this::writeAnnotationSetRefList,
+ 4);
+ writeItems(
+ mixedSectionLayoutStrategy.getAnnotationDirectoryLayout(),
+ layout::setAnnotationDirectoriesOffset,
+ this::writeAnnotationDirectory,
+ 4);
- // Add the map at the end.
- writeMap(layout);
- layout.setEndOfFile(dest.position());
+ // Add the map at the end.
+ writeMap(layout);
+ layout.setEndOfFile(dest.position());
+ }
// Now that we have all mixedSectionOffsets, lets write the indexed items.
- dest.moveTo(layout.headerOffset + layout.getHeaderSize());
- if (includeStringData) {
- writeFixedSectionItems(mapping.getStrings(), layout.stringIdsOffset, this::writeStringItem);
- } else {
- assert layout.stringIdsOffset == layout.typeIdsOffset;
+ try (Timing t0 = timing.begin("Write indexed items")) {
+ dest.moveTo(layout.headerOffset + layout.getHeaderSize());
+ if (includeStringData) {
+ writeFixedSectionItems(mapping.getStrings(), layout.stringIdsOffset, this::writeStringItem);
+ } else {
+ assert layout.stringIdsOffset == layout.typeIdsOffset;
+ }
+ writeFixedSectionItems(mapping.getTypes(), layout.typeIdsOffset, this::writeTypeItem);
+ writeFixedSectionItems(mapping.getProtos(), layout.protoIdsOffset, this::writeProtoItem);
+ writeFixedSectionItems(mapping.getFields(), layout.fieldIdsOffset, this::writeFieldItem);
+ writeFixedSectionItems(mapping.getMethods(), layout.methodIdsOffset, this::writeMethodItem);
+ writeFixedSectionItems(mapping.getClasses(), layout.classDefsOffset, this::writeClassDefItem);
+ writeFixedSectionItems(mapping.getCallSites(), layout.callSiteIdsOffset, this::writeCallSite);
+ writeFixedSectionItems(
+ mapping.getMethodHandles(), layout.methodHandleIdsOffset, this::writeMethodHandle);
}
- writeFixedSectionItems(mapping.getTypes(), layout.typeIdsOffset, this::writeTypeItem);
- writeFixedSectionItems(mapping.getProtos(), layout.protoIdsOffset, this::writeProtoItem);
- writeFixedSectionItems(mapping.getFields(), layout.fieldIdsOffset, this::writeFieldItem);
- writeFixedSectionItems(mapping.getMethods(), layout.methodIdsOffset, this::writeMethodItem);
- writeFixedSectionItems(mapping.getClasses(), layout.classDefsOffset, this::writeClassDefItem);
- writeFixedSectionItems(mapping.getCallSites(), layout.callSiteIdsOffset, this::writeCallSite);
- writeFixedSectionItems(
- mapping.getMethodHandles(), layout.methodHandleIdsOffset, this::writeMethodHandle);
// Fill in the header information.
writeHeader(layout, layoutType);