Kürzlich hatte ich einige Tests über Java MappedByteBuffer. Ich fand heraus, dass wenn ich kontinuierlich die gleiche Datei abdecke und lese, die Zeit, die ich damit verbringe, länger und länger zu lesen. Aber wenn ich die Kartengröße nicht ändere, wäre es schneller als das ich die gleiche Kartengröße im Map Size Variation Test verwende.Java MappedByteBuffer Leistung immer schlechter, wenn Sie die Kartengröße kontinuierlich ändern
Ich habe eine Datei "DataFile" in 1GB, die mit Ganzzahlen gefüllt.
private final File dataFile = new File("~/testfile");
private final int intNum = 1024 * 1024 * 1024/4; // 1GB Integers
@Test
public void writeFile() throws Exception {
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile)));
for (int i = 0; i < intNum; i++) {
dos.writeInt(RandomUtils.nextInt());
}
dos.close();
}
und ein Verfahren darüber
// read this dataFile in a loop with fixed map size
private void bufferSizePerformanceTest(final int buffSize) throws Exception {
Stopwatch stopwatch = Stopwatch.createStarted();
FileChannel fc = new RandomAccessFile(dataFile, "r").getChannel();
MappedByteBuffer buffer;
final int readPerLoop = buffSize/4;
int currentLen = 0;
int readCount = 0;
for (int i = 1; ; i++) {
int i1 = i * buffSize;
if (i1 >= dataFile.length()) {
buffer = fc.map(FileChannel.MapMode.READ_ONLY, currentLen, dataFile.length() - currentLen);
for (int j = 0; j < readPerLoop; j++) {
buffer.getInt();
readCount++;
}
break;
} else {
buffer = fc.map(FileChannel.MapMode.READ_ONLY, currentLen, buffSize);
currentLen = i1;
}
for (int j = 0; j < readPerLoop; j++) {
buffer.getInt();
readCount++;
}
}
fc.close();
// ByteBufferUtil.releaseByteBuffer(buffer);
// System.gc();
System.out.println("readCount : " + readCount + " raf buffer size " + getMBytes(buffSize) + " MB : " + stopwatch.elapsed(TimeUnit.MILLISECONDS));
}
Die Variation BUFFSIZE Test
private static int getMBytes(int bytes) {
return bytes/1024/1024;
}
// get the power of 2 by n
private static int getM(int n) {
return (int) (Math.log10(n)/Math.log10(2));
}
@Test
public void testBuffSizeReadPerformance() throws Exception {
System.out.println(ManagementFactory.getRuntimeMXBean().getName());
for (int i = 0; i <= getM(1024); i++) {
Thread.sleep(1000);
bufferSizePerformanceTest((int) (Math.pow(2, i) * 1024 * 1024));
}
}
Variation Ausgänge Lesen:
[email protected]
readCount : 268435456 raf buffer size 1 MB : 122
readCount : 268435456 raf buffer size 2 MB : 133
readCount : 268435456 raf buffer size 4 MB : 29
readCount : 268435456 raf buffer size 8 MB : 35
readCount : 268435456 raf buffer size 16 MB : 38
readCount : 268435456 raf buffer size 32 MB : 124
readCount : 268435456 raf buffer size 64 MB : 241
readCount : 268435456 raf buffer size 128 MB : 456
readCount : 268435456 raf buffer size 256 MB : 1086
readCount : 268435456 raf buffer size 512 MB : 2458
readCount : 268435456 raf buffer size 1024 MB : 4952
Der feste BUFFSIZE Test:
@Test
public void testBuffSizeReadPerformance2() throws Exception {
System.out.println(ManagementFactory.getRuntimeMXBean().getName());
for (int i = 0; i < 10; i++) {
bufferSizePerformanceTest(1024 * 1024 * 1024);
}
}
Ausgabe
[email protected]
readCount : 268435456 raf buffer size 1024 MB : 127
readCount : 268435456 raf buffer size 1024 MB : 111
readCount : 268435456 raf buffer size 1024 MB : 20
readCount : 268435456 raf buffer size 1024 MB : 17
readCount : 268435456 raf buffer size 1024 MB : 23
readCount : 268435456 raf buffer size 1024 MB : 19
readCount : 268435456 raf buffer size 1024 MB : 21
readCount : 268435456 raf buffer size 1024 MB : 22
readCount : 268435456 raf buffer size 1024 MB : 20
readCount : 268435456 raf buffer size 1024 MB : 33
Wie die 2 Tests zeigen, die mit dem gleichen BUFFSIZE (1024MB) verbrachte Zeit beim Lesen ist in zwei Tests ganz anders. Der Test mit fester buffSize ist viel schneller als der Variationstest.
Meine Frage ist: 1. Wie ist das passiert, warum wird es schneller? 2. Besetzt der MappedByteBuffer physischen Speicher? Wie ich im ActivityMonitor sehe, wird es keinen physischen Speicher belegen.
Dank
----- ----- Update-
Der Freigabepuffercode:
public static void releaseByteBuffer(ByteBuffer buffer) throws NoSuchFieldException, IllegalAccessException {
Cleaner cleaner = ((DirectBuffer) buffer).cleaner();
cleaner.clean();
}
Ich glaube nicht, dass die Ursache für dieses Problem Speichernutzung ist. Weil es die gleiche Ausgabe hat, selbst wenn ich den Freigabecode und den GC-Code einschalte. Wie auch immer, wenn es um die Speichernutzung geht, setze ich die Schleifenzeiten im zweiten Test auf 100, sollte mehr Speicher als der erste Test verbrauchen, aber es ist schneller als der erste.
----- ----- Update 2
Wenn ich die BUFFSIZE drehe 1 statt Erhöhung des Tests zu verringern, das Problem verschwinden.
@Test
public void testBuffSizeReadPerformance3() throws Exception {
System.out.println(ManagementFactory.getRuntimeMXBean().getName());
for (int i = getM(1024); i >= 0; i--) {
bufferSizePerformanceTest((int) (Math.pow(2, i) * 1024 * 1024));
}
}
Ausgang:
[email protected]
readCount : 268435456 raf buffer size 1024 MB : 101
readCount : 268435456 raf buffer size 512 MB : 187
readCount : 268435456 raf buffer size 256 MB : 31
readCount : 268435456 raf buffer size 128 MB : 30
readCount : 268435456 raf buffer size 64 MB : 36
readCount : 268435456 raf buffer size 32 MB : 37
readCount : 268435456 raf buffer size 16 MB : 37
readCount : 268435456 raf buffer size 8 MB : 32
readCount : 268435456 raf buffer size 4 MB : 44
readCount : 268435456 raf buffer size 2 MB : 34
readCount : 268435456 raf buffer size 1 MB : 55
Dank @EJP, siehe mein Update. – Alexis
Ich muß sagen, dass ich den Zweck Ihres Testcode nicht verstehen, aber wenn man Sie wahrscheinlich den gleichen zugrunde liegenden Bildspeicher immer eher als ein anderen Brocken immer sind nicht die Kartengröße ändern, die virtuellen Speicher speichert. Ich weiß nicht, welchen Zweck es hätte, es zu ändern. – EJP
ich finden will, ist es etwas auf die Effizienz des Lesens einer Datei beeinflussen, wenn verschiedene Kartengröße verwenden, so schreibe ich diesen Code. Und ich möchte wissen, ob ich eine Datei in 1 GB lesen, welche Kartengröße ich verwenden soll. – Alexis