summaryrefslogtreecommitdiffstats
path: root/dx
diff options
context:
space:
mode:
authorPiotr Jastrzebski <haaawk@google.com>2015-03-05 16:47:32 +0000
committerPiotr Jastrzebski <haaawk@google.com>2015-03-06 07:50:16 +0000
commit461e201ba8f1e15754c8966c02d18d76e67537a4 (patch)
tree57bf1ccb1d6c207deda024ced853b49303c3fe77 /dx
parent4d1fa0045be86fc3bc8deadb81b757dcb95aac24 (diff)
downloadtoolchain_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.java130
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 {