C: improve performance of heap dump to hprof converter

This commit is contained in:
Alexey Andreev 2019-11-05 14:01:56 +03:00
parent b60d57ea73
commit c05f40cc6a
2 changed files with 116 additions and 15 deletions

View File

@ -0,0 +1,99 @@
/*
* Copyright 2019 konsoletyper.
*
* 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.
*/
package org.teavm.backend.c.util;
import java.io.IOException;
import java.io.RandomAccessFile;
class BufferedFile {
private RandomAccessFile out;
private byte[] buffer;
private int pos;
BufferedFile(RandomAccessFile out) {
this.out = out;
buffer = new byte[4096];
}
void flush() throws IOException {
if (pos > 0) {
out.write(buffer, 0, pos);
pos = 0;
}
}
void writeInt(int v) throws IOException {
byte[] buffer = this.buffer;
int localPos = pos;
if (localPos + 4 >= buffer.length) {
flush();
localPos = pos;
}
buffer[localPos++] = (byte) (v >>> 24);
buffer[localPos++] = (byte) ((v >>> 16) & 255);
buffer[localPos++] = (byte) ((v >>> 8) & 255);
buffer[localPos++] = (byte) (v & 255);
pos = localPos;
}
void writeShort(int v) throws IOException {
byte[] buffer = this.buffer;
int localPos = pos;
if (localPos + 2 >= buffer.length) {
flush();
localPos = pos;
}
buffer[localPos++] = (byte) ((v >>> 8) & 255);
buffer[localPos++] = (byte) (v & 255);
pos = localPos;
}
void write(byte[] data) throws IOException {
write(data, 0, data.length);
}
void write(byte[] data, int start, int length) throws IOException {
if (pos + length >= buffer.length) {
flush();
}
if (length > buffer.length) {
out.write(data, start, length);
} else {
System.arraycopy(data, start, buffer, pos, length);
pos += length;
}
}
void write(int b) throws IOException {
if (pos + 1 >= buffer.length) {
flush();
}
buffer[pos++] = (byte) b;
}
long getFilePointer() throws IOException {
return out.getFilePointer() + pos;
}
void seek(long pointer) throws IOException {
flush();
out.seek(pointer);
}
}

View File

@ -21,7 +21,6 @@ import com.carrotsearch.hppc.LongObjectMap;
import com.carrotsearch.hppc.ObjectIntHashMap; import com.carrotsearch.hppc.ObjectIntHashMap;
import com.carrotsearch.hppc.ObjectIntMap; import com.carrotsearch.hppc.ObjectIntMap;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.DataOutput;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@ -215,9 +214,12 @@ public final class HeapDumpConverter {
output.write("JAVA PROFILE 1.0.2\0".getBytes(StandardCharsets.UTF_8)); output.write("JAVA PROFILE 1.0.2\0".getBytes(StandardCharsets.UTF_8));
output.writeInt(idSize); output.writeInt(idSize);
output.writeLong(System.currentTimeMillis()); output.writeLong(System.currentTimeMillis());
writeSymbols(output, symbolTable);
writeStack(output, symbolTable); BufferedFile bufferedOutput = new BufferedFile(output);
writeHeapDump(reader, output, symbolTable); writeSymbols(bufferedOutput, symbolTable);
writeStack(bufferedOutput, symbolTable);
writeHeapDump(reader, bufferedOutput, symbolTable);
bufferedOutput.flush();
output.write(0x2C); output.write(0x2C);
output.writeInt(0); output.writeInt(0);
@ -225,7 +227,7 @@ public final class HeapDumpConverter {
output.setLength(output.getFilePointer()); output.setLength(output.getFilePointer());
} }
private static void writeSymbols(RandomAccessFile output, SymbolTable symbolTable) throws IOException { private static void writeSymbols(BufferedFile output, SymbolTable symbolTable) throws IOException {
List<String> strings = symbolTable.getStrings(); List<String> strings = symbolTable.getStrings();
for (int i = 0; i < strings.size(); ++i) { for (int i = 0; i < strings.size(); ++i) {
byte[] bytes = strings.get(i).getBytes(StandardCharsets.UTF_8); byte[] bytes = strings.get(i).getBytes(StandardCharsets.UTF_8);
@ -238,7 +240,7 @@ public final class HeapDumpConverter {
} }
} }
private static void writeStack(RandomAccessFile output, SymbolTable symbolTable) throws IOException { private static void writeStack(BufferedFile output, SymbolTable symbolTable) throws IOException {
for (int i = 0; i < symbolTable.stack.size(); ++i) { for (int i = 0; i < symbolTable.stack.size(); ++i) {
Frame frame = symbolTable.stack.get(i); Frame frame = symbolTable.stack.get(i);
output.write(4); output.write(4);
@ -271,7 +273,7 @@ public final class HeapDumpConverter {
} }
} }
private static void writeGcRoots(RandomAccessFile output, SymbolTable symbolTable) throws IOException { private static void writeGcRoots(BufferedFile output, SymbolTable symbolTable) throws IOException {
List<Frame> stack = symbolTable.stack; List<Frame> stack = symbolTable.stack;
for (int i = 0; i < stack.size(); i++) { for (int i = 0; i < stack.size(); i++) {
Frame frame = stack.get(i); Frame frame = stack.get(i);
@ -295,7 +297,7 @@ public final class HeapDumpConverter {
} }
} }
private static void writeHeapDump(Reader reader, RandomAccessFile output, SymbolTable symbolTable) private static void writeHeapDump(Reader reader, BufferedFile output, SymbolTable symbolTable)
throws IOException { throws IOException {
for (ClassDescriptor classDescriptor : symbolTable.getClasses()) { for (ClassDescriptor classDescriptor : symbolTable.getClasses()) {
if (classDescriptor.primitiveType != null) { if (classDescriptor.primitiveType != null) {
@ -330,7 +332,7 @@ public final class HeapDumpConverter {
output.seek(pointerBackup); output.seek(pointerBackup);
} }
private static void writeClassObjects(RandomAccessFile output, SymbolTable symbolTable) throws IOException { private static void writeClassObjects(BufferedFile output, SymbolTable symbolTable) throws IOException {
Collection<ClassDescriptor> classes = symbolTable.getClasses(); Collection<ClassDescriptor> classes = symbolTable.getClasses();
for (ClassDescriptor cls : classes) { for (ClassDescriptor cls : classes) {
if (cls.primitiveType == null) { if (cls.primitiveType == null) {
@ -339,7 +341,7 @@ public final class HeapDumpConverter {
} }
} }
private static void writeClassDump(RandomAccessFile output, SymbolTable symbolTable, ClassDescriptor cls) private static void writeClassDump(BufferedFile output, SymbolTable symbolTable, ClassDescriptor cls)
throws IOException { throws IOException {
output.write(0x20); output.write(0x20);
writeId(output, cls.id); writeId(output, cls.id);
@ -377,14 +379,14 @@ public final class HeapDumpConverter {
} }
static class ObjectDumpVisitor extends JsonAllErrorVisitor { static class ObjectDumpVisitor extends JsonAllErrorVisitor {
private DataOutput output; private BufferedFile output;
private SymbolTable symbolTable; private SymbolTable symbolTable;
private JsonPropertyVisitor propertyVisitor = new JsonPropertyVisitor(true); private JsonPropertyVisitor propertyVisitor = new JsonPropertyVisitor(true);
private long id; private long id;
private long classId; private long classId;
private byte[] data; private byte[] data;
ObjectDumpVisitor(DataOutput output, SymbolTable symbolTable) { ObjectDumpVisitor(BufferedFile output, SymbolTable symbolTable) {
this.output = output; this.output = output;
this.symbolTable = symbolTable; this.symbolTable = symbolTable;
propertyVisitor.addProperty("id", idVisitor); propertyVisitor.addProperty("id", idVisitor);
@ -437,7 +439,7 @@ public final class HeapDumpConverter {
if (itemCls.primitiveType == null) { if (itemCls.primitiveType == null) {
writeId(output, classId); writeId(output, classId);
} else { } else {
output.writeByte(typeToInt(itemCls.primitiveType)); output.write(typeToInt(itemCls.primitiveType));
} }
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
int ptr = i * itemSize; int ptr = i * itemSize;
@ -869,11 +871,11 @@ public final class HeapDumpConverter {
} }
} }
private static void writeId(DataOutput out, long id) throws IOException { private static void writeId(BufferedFile out, long id) throws IOException {
writeLongBytes(out, id, idSize); writeLongBytes(out, id, idSize);
} }
private static void writeLongBytes(DataOutput out, long v, int size) throws IOException { private static void writeLongBytes(BufferedFile out, long v, int size) throws IOException {
for (int i = size - 1; i >= 0; --i) { for (int i = size - 1; i >= 0; --i) {
buffer[i] = (byte) (v & 255); buffer[i] = (byte) (v & 255);
v >>>= 8; v >>>= 8;