Omaha #3093 Add option to hprof tool to zero primitive arrays for compression.

Former-commit-id: 6a80964572cf331b433ae8dc222ac209dd35bf63
This commit is contained in:
Ben Steffensmeier 2014-05-20 17:42:08 -05:00
parent f19fda01ad
commit df62609973
6 changed files with 105 additions and 35 deletions

View file

@ -19,8 +19,8 @@
**/ **/
package com.raytheon.hprof; package com.raytheon.hprof;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.BufferUnderflowException; import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
@ -40,6 +40,7 @@ import java.nio.channels.FileChannel.MapMode;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Jan 08, 2014 2648 bsteffen Initial doc * Jan 08, 2014 2648 bsteffen Initial doc
* May 20, 2014 3093 bsteffen Allow read/write
* *
* </pre> * </pre>
* *
@ -62,9 +63,12 @@ public class BigByteBuffer {
private long limit; private long limit;
public BigByteBuffer(String fileName) throws IOException { public BigByteBuffer(String fileName, boolean readOnly) throws IOException {
FileInputStream fis = new FileInputStream(fileName); String mode = readOnly ? "r" : "rw";
FileChannel fileChannel = fis.getChannel(); RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(fileName, mode);
FileChannel fileChannel = raf.getChannel();
offset = 0; offset = 0;
limit = capacity = fileChannel.size(); limit = capacity = fileChannel.size();
int nBuffers = (int) (capacity / chunkSize); int nBuffers = (int) (capacity / chunkSize);
@ -72,11 +76,16 @@ public class BigByteBuffer {
nBuffers += 1; nBuffers += 1;
} }
buffers = new ByteBuffer[nBuffers]; buffers = new ByteBuffer[nBuffers];
MapMode mapMode = readOnly ? MapMode.READ_ONLY : MapMode.READ_WRITE;
for (int i = 0; i < buffers.length; i += 1) { for (int i = 0; i < buffers.length; i += 1) {
buffers[i] = fileChannel.map(MapMode.READ_ONLY, i * chunkSize, buffers[i] = fileChannel.map(mapMode, i * chunkSize,
Math.min(capacity - i * chunkSize, chunkSize)); Math.min(capacity - i * chunkSize, chunkSize));
} }
fis.close(); } finally {
if (raf != null) {
raf.close();
}
}
} }
protected BigByteBuffer(ByteBuffer[] buffers, long offset, long capacity) { protected BigByteBuffer(ByteBuffer[] buffers, long offset, long capacity) {
@ -146,6 +155,17 @@ public class BigByteBuffer {
return getBuffer(index).get(bufferIndex(index)); return getBuffer(index).get(bufferIndex(index));
} }
public BigByteBuffer put(byte b) {
put(nextGetIndex(), b);
return this;
}
public BigByteBuffer put(long index, byte b) {
checkIndex(index);
getBuffer(index).put(bufferIndex(index), b);
return this;
}
public void get(byte[] dst) { public void get(byte[] dst) {
long start = nextGetIndex(dst.length); long start = nextGetIndex(dst.length);
ByteBuffer buffer = getBuffer(start); ByteBuffer buffer = getBuffer(start);

View file

@ -51,6 +51,7 @@ import com.raytheon.hprof.data.heap.dump.InstanceDump;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Jan 08, 2014 2648 bsteffen Initial doc * Jan 08, 2014 2648 bsteffen Initial doc
* May 20, 2014 3093 bsteffen Allow opening for write.
* *
* </pre> * </pre>
* *
@ -70,8 +71,8 @@ public class HprofFile {
private Map<Id, String> usedClassnames = new HashMap<Id, String>(); private Map<Id, String> usedClassnames = new HashMap<Id, String>();
public HprofFile(String fileName) throws IOException { public HprofFile(String fileName, boolean readOnly) throws IOException {
BigByteBuffer buffer = new BigByteBuffer(fileName); BigByteBuffer buffer = new BigByteBuffer(fileName, readOnly);
String format = null; String format = null;

View file

@ -55,6 +55,7 @@ import com.raytheon.hprof.data.heap.root.RootThreadObject;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Jan 08, 2014 2648 bsteffen Initial doc * Jan 08, 2014 2648 bsteffen Initial doc
* May 20, 2014 3093 bsteffen Add zeroPrimitiveArrays
* *
* </pre> * </pre>
* *
@ -137,12 +138,12 @@ public class HeapDumpRecord extends AbstractHprofRecord {
} }
case ObjectArrayDump.TAG: { case ObjectArrayDump.TAG: {
objectArrays.add(buffer.position()); objectArrays.add(buffer.position());
new ObjectArrayDump(buffer, idSize); new ObjectArrayDump(buffer, idSize, false);
break; break;
} }
case PrimitiveArrayDump.TAG: { case PrimitiveArrayDump.TAG: {
primitiveArrays.add(buffer.position()); primitiveArrays.add(buffer.position());
new PrimitiveArrayDump(buffer, idSize); new PrimitiveArrayDump(buffer, idSize, false);
break; break;
} }
case HeapDumpSegmentRecord.TAG: { case HeapDumpSegmentRecord.TAG: {
@ -234,7 +235,7 @@ public class HeapDumpRecord extends AbstractHprofRecord {
return null; return null;
} }
buffer.position(index); buffer.position(index);
return new ObjectArrayDump(buffer, idSize); return new ObjectArrayDump(buffer, idSize, true);
} }
public BasicType[] getPrimitiveArray(Id objectId) { public BasicType[] getPrimitiveArray(Id objectId) {
@ -243,7 +244,29 @@ public class HeapDumpRecord extends AbstractHprofRecord {
return null; return null;
} }
buffer.position(index); buffer.position(index);
return new PrimitiveArrayDump(buffer, idSize).getArray(); return new PrimitiveArrayDump(buffer, idSize, true).getArray();
}
/**
* Zero out all data for non char primitive arrays in the backing file.
*/
public void zeroPrimitiveArrays() {
for (long index : primitiveArraysById) {
buffer.position(index);
PrimitiveArrayDump dump = new PrimitiveArrayDump(buffer, idSize,
true);
BasicType[] array = dump.getArray();
if (array.length > 0) {
BasicType sample = array[0];
if (!sample.isChar()) {
int size = sample.getSize() * array.length;
buffer.position(buffer.position() - size);
for (int i = 0; i < size; i += 1) {
buffer.put((byte) 0);
}
}
}
}
} }
private long binarySearch(long[] array, Id objectId) { private long binarySearch(long[] array, Id objectId) {

View file

@ -34,6 +34,7 @@ import com.raytheon.hprof.data.HeapDumpRecord;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Jan 08, 2014 2648 bsteffen Initial doc * Jan 08, 2014 2648 bsteffen Initial doc
* May 20, 2014 3093 bsteffen Allow creation without reading full array.
* *
* </pre> * </pre>
* *
@ -48,14 +49,19 @@ public class ObjectArrayDump extends AbstractDump {
private final Id[] array; private final Id[] array;
public ObjectArrayDump(BigByteBuffer buffer, int idSize) { public ObjectArrayDump(BigByteBuffer buffer, int idSize, boolean readArray) {
super(buffer, idSize); super(buffer, idSize);
int numElements = buffer.getInt(); int numElements = buffer.getInt();
arrayClassId = new Id(buffer, idSize); arrayClassId = new Id(buffer, idSize);
if (readArray) {
array = new Id[numElements]; array = new Id[numElements];
for (int i = 0; i < numElements; i++) { for (int i = 0; i < numElements; i++) {
array[i] = new Id(buffer, idSize); array[i] = new Id(buffer, idSize);
} }
} else {
array = null;
buffer.position(buffer.position() + idSize * numElements);
}
} }
public Id[] getArray() { public Id[] getArray() {

View file

@ -34,6 +34,7 @@ import com.raytheon.hprof.data.heap.BasicType;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Jan 08, 2014 2648 bsteffen Initial doc * Jan 08, 2014 2648 bsteffen Initial doc
* May 20, 2014 3093 bsteffen Allow creation without reading full array.
* *
* </pre> * </pre>
* *
@ -46,14 +47,22 @@ public class PrimitiveArrayDump extends AbstractDump {
private final BasicType[] array; private final BasicType[] array;
public PrimitiveArrayDump(BigByteBuffer buffer, int idSize) { public PrimitiveArrayDump(BigByteBuffer buffer, int idSize,
boolean readArray) {
super(buffer, idSize); super(buffer, idSize);
int numElements = buffer.getInt(); int numElements = buffer.getInt();
byte type = buffer.get(); byte type = buffer.get();
if (readArray) {
array = new BasicType[numElements]; array = new BasicType[numElements];
for (int i = 0; i < numElements; i++) { for (int i = 0; i < numElements; i++) {
array[i] = new BasicType(buffer, type, idSize); array[i] = new BasicType(buffer, type, idSize);
} }
} else {
array = null;
BasicType tmp = new BasicType(buffer, type, idSize);
int skip = (numElements - 1) * tmp.getSize();
buffer.position(buffer.position() + skip);
}
} }
public BasicType[] getArray() { public BasicType[] getArray() {

View file

@ -37,6 +37,7 @@ import com.raytheon.hprof.HprofFile;
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Jan 08, 2014 2648 bsteffen Initial doc * Jan 08, 2014 2648 bsteffen Initial doc
* May 05, 2014 3093 bsteffen Add some new exporters * May 05, 2014 3093 bsteffen Add some new exporters
* May 20, 2014 3093 bsteffen Add option to zero primitive arrays.
* *
* </pre> * </pre>
* *
@ -51,17 +52,27 @@ public class CaveExporter {
.println("Provide some args, an hprof file is required, an output directory is optional."); .println("Provide some args, an hprof file is required, an output directory is optional.");
System.exit(1); System.exit(1);
} }
HprofFile hprof; int argIdx = 0;
HprofFile hprof = null;
try { try {
hprof = new HprofFile(args[0]); if (args[argIdx].equals("-zero")) {
System.out.println("Writing 0s...");
hprof = new HprofFile(args[argIdx + 1], false);
hprof.getHeapDump().zeroPrimitiveArrays();
argIdx += 2;
} else {
hprof = new HprofFile(args[argIdx], true);
argIdx += 1;
}
} catch (IOException e) { } catch (IOException e) {
throw new IllegalArgumentException("Error opening hprof file: " throw new IllegalArgumentException("Error opening hprof file: "
+ args[0], e); + args[argIdx], e);
} }
File outputDir = null; File outputDir = null;
if (args.length > 1) { if (args.length > 1) {
outputDir = new File(args[1]); outputDir = new File(args[argIdx++]);
} else { } else {
outputDir = new File("."); outputDir = new File(".");
} }