diff options
author | Piotr Jastrzebski <haaawk@google.com> | 2015-03-05 16:47:32 +0000 |
---|---|---|
committer | Piotr Jastrzebski <haaawk@google.com> | 2015-03-06 07:50:16 +0000 |
commit | 461e201ba8f1e15754c8966c02d18d76e67537a4 (patch) | |
tree | 57bf1ccb1d6c207deda024ced853b49303c3fe77 /dx | |
parent | 4d1fa0045be86fc3bc8deadb81b757dcb95aac24 (diff) | |
download | toolchain_jack-461e201ba8f1e15754c8966c02d18d76e67537a4.zip toolchain_jack-461e201ba8f1e15754c8966c02d18d76e67537a4.tar.gz toolchain_jack-461e201ba8f1e15754c8966c02d18d76e67537a4.tar.bz2 |
Read some sections of dex in DexBuffer constructor
I profiled the incremental compilation of Music app and it showed
that we are reading and creating 1,330,524 strings from dex files
in DexBuffers. I checked and the total of strings in all dex files
represented by DexBuffers is 284979. That's around 20% of what we
were reading. The conclusion was that we read the same strings
over and over again. Then I looked at ConstantManager.addDexFile
and it striked me that we need all strings, typeIds, typeNames,
fieldIds and methodIds anyway because we iterate over them in
addDexFile. This means that we can as well read all of them
when DexBuffer is created. This way we save a lot of cpu and
memory allocations. Strings alone were taking 70MB of heap.
Now we're allocating only 20% of it.
This change speeds up incremental compilation by over 12.5%.
Change-Id: Iee18e9d17419886e552e3fd0b1143d2bb7220c9c
Diffstat (limited to 'dx')
-rw-r--r-- | dx/src/com/android/jack/dx/io/DexBuffer.java | 130 |
1 files changed, 69 insertions, 61 deletions
diff --git a/dx/src/com/android/jack/dx/io/DexBuffer.java b/dx/src/com/android/jack/dx/io/DexBuffer.java index edecf54..8f3c7c3 100644 --- a/dx/src/com/android/jack/dx/io/DexBuffer.java +++ b/dx/src/com/android/jack/dx/io/DexBuffer.java @@ -54,45 +54,11 @@ public final class DexBuffer { private final TableOfContents tableOfContents = new TableOfContents(); private int length = 0; - private final List<String> strings = new AbstractList<String>() { - @Override - public String get(int index) { - checkBounds(index, tableOfContents.stringIds.size); - return open(tableOfContents.stringIds.off + (index * SizeOf.STRING_ID_ITEM)).readString(); - } + private final List<String> strings; - @Override - public int size() { - return tableOfContents.stringIds.size; - } - }; + private final List<Integer> typeIds; - private final List<Integer> typeIds = new AbstractList<Integer>() { - @Override - public Integer get(int index) { - checkBounds(index, tableOfContents.typeIds.size); - return Integer.valueOf( - open(tableOfContents.typeIds.off + (index * SizeOf.TYPE_ID_ITEM)).readInt()); - } - - @Override - public int size() { - return tableOfContents.typeIds.size; - } - }; - - private final List<String> typeNames = new AbstractList<String>() { - @Override - public String get(int index) { - checkBounds(index, tableOfContents.typeIds.size); - return strings.get(typeIds.get(index).intValue()); - } - - @Override - public int size() { - return tableOfContents.typeIds.size; - } - }; + private final List<String> typeNames; private final List<ProtoId> protoIds = new AbstractList<ProtoId>() { @Override @@ -107,37 +73,20 @@ public final class DexBuffer { } }; - private final List<FieldId> fieldIds = new AbstractList<FieldId>() { - @Override - public FieldId get(int index) { - checkBounds(index, tableOfContents.fieldIds.size); - return open(tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * index)).readFieldId(); - } - - @Override - public int size() { - return tableOfContents.fieldIds.size; - } - }; - - private final List<MethodId> methodIds = new AbstractList<MethodId>() { - @Override - public MethodId get(int index) { - checkBounds(index, tableOfContents.methodIds.size); - return open(tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * index)).readMethodId(); - } + private final List<FieldId> fieldIds; - @Override - public int size() { - return tableOfContents.methodIds.size; - } - }; + private final List<MethodId> methodIds; /** * Creates a new dex buffer defining no classes. */ public DexBuffer() { this.data = new byte[0]; + this.strings = Collections.emptyList(); + this.typeIds = Collections.emptyList(); + this.typeNames = Collections.emptyList(); + this.fieldIds = Collections.emptyList(); + this.methodIds = Collections.emptyList(); } /** @@ -148,6 +97,11 @@ public final class DexBuffer { this.data = data; this.length = data.length; this.tableOfContents.readFrom(this); + this.strings = readStrings(); + this.typeIds = readTypeIds(); + this.typeNames = readTypeNames(this.strings, this.typeIds); + this.fieldIds = readFieldIds(); + this.methodIds = readMethodIds(); } /** @@ -155,6 +109,11 @@ public final class DexBuffer { */ public DexBuffer(InputStream in) throws IOException { loadFrom(in); + this.strings = readStrings(); + this.typeIds = readTypeIds(); + this.typeNames = readTypeNames(this.strings, this.typeIds); + this.fieldIds = readFieldIds(); + this.methodIds = readMethodIds(); } /** @@ -176,6 +135,55 @@ public final class DexBuffer { } else { throw new DexException("unknown output extension: " + file); } + this.strings = readStrings(); + this.typeIds = readTypeIds(); + this.typeNames = readTypeNames(this.strings, this.typeIds); + this.fieldIds = readFieldIds(); + this.methodIds = readMethodIds(); + } + + private List<String> readStrings() { + Section strings = open(tableOfContents.stringIds.off); + String[] result = new String[tableOfContents.stringIds.size]; + for (int i = 0; i < tableOfContents.stringIds.size; ++i) { + result[i] = strings.readString(); + } + return Arrays.asList(result); + } + + private List<Integer> readTypeIds() { + Section typeIds = open(tableOfContents.typeIds.off); + Integer[] result = new Integer[tableOfContents.typeIds.size]; + for (int i = 0; i < tableOfContents.typeIds.size; ++i) { + result[i] = Integer.valueOf(typeIds.readInt()); + } + return Arrays.asList(result); + } + + private List<String> readTypeNames(List<String> strings, List<Integer> typeIds) { + String[] result = new String[tableOfContents.typeIds.size]; + for (int i = 0; i < tableOfContents.typeIds.size; ++i) { + result[i] = strings.get(typeIds.get(i).intValue()); + } + return Arrays.asList(result); + } + + private List<FieldId> readFieldIds() { + Section fieldIds = open(tableOfContents.fieldIds.off); + FieldId[] result = new FieldId[tableOfContents.fieldIds.size]; + for (int i = 0; i < tableOfContents.fieldIds.size; ++i) { + result[i] = fieldIds.readFieldId(); + } + return Arrays.asList(result); + } + + private List<MethodId> readMethodIds() { + Section methodIds = open(tableOfContents.methodIds.off); + MethodId[] result = new MethodId[tableOfContents.methodIds.size]; + for (int i = 0; i < tableOfContents.methodIds.size; ++i) { + result[i] = methodIds.readMethodId(); + } + return Arrays.asList(result); } private void loadFrom(InputStream in) throws IOException { |