2016-05-25 8 views
1

最近、私はJava MappedByteBufferに関するいくつかのテストを行った。私は、同じファイルを連続的にマップして読み込むと、読み込み時間が長くて長くかかることが分かりました。しかし、私が地図のサイズを変更しなかった場合、私は地図のサイズの変化のテストで同じマップのサイズを使用するよりも速くなります。マップサイズを連続的に変更するとJava MappedByteBufferのパフォーマンスが悪化して悪化する

私は、整数で満たされた1GBのファイル "dataFile"を持っています。

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(); 
} 

そして

// 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)); 
} 

変化BUFFSIZE試験

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)); 
    } 
} 

バリエーション出力する読み出し約方法:

[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 

固定BUFFSIZE試験:

試験が示すように
@Test 
public void testBuffSizeReadPerformance2() throws Exception { 
    System.out.println(ManagementFactory.getRuntimeMXBean().getName()); 

    for (int i = 0; i < 10; i++) { 
     bufferSizePerformanceTest(1024 * 1024 * 1024); 
    } 
} 

出力

[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 

、同じBUFFSIZE(1024メガバイト)と読み取りに費やされた時間は、2回の試験ではかなり異なっています。 fixed buffSizeを使用したテストは、バリエーションテストよりもはるかに高速です。

私の質問は: 1.これはどうして起こったのです、なぜ速くなるのでしょうか? 2. MappedByteBufferは物理メモリを占有していますか? ActivityMonitorに表示されるように、物理メモリを占有しません。

おかげ

-----更新-----

リリースバッファコード:

public static void releaseByteBuffer(ByteBuffer buffer) throws NoSuchFieldException, IllegalAccessException { 
    Cleaner cleaner = ((DirectBuffer) buffer).cleaner(); 
    cleaner.clean(); 
} 

私は、この問題の原因はメモリ使用量ではないと思います。それはリリースコードとgcコードをオンにしても同じ出力を持っているからです。とにかく、メモリ使用量については、2回目のテストでループ時間を100に設定し、最初のテストよりも多くのメモリを使用する必要がありますが、最初のテストよりも高速です。

-----アップデート2 -----

私が代わりにテスト1の増加により減少しBUFFSIZEを有効にした場合、問題が消えます。

@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)); 
    } 
} 

出力:

[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 

答えて

1

あなたは「マップのサイズcontinuously'.Youが新しいマップを作成しておく変更されていない、とのマッピングがリリースされることにより、機構がない、GCを含め、あなたはますます多くのメモリを使用しています。

可能な限りMappedByteBuffersを使用することを目指してください。サイズを大きくする必要があるかもしれません。

私はByteBufferUtil.releaseByteBuffer(buffer)が何であるか、どこから来たのかわかりませんが、これらの性質は信頼できません。

+0

ありがとう@EJP、私の更新を参照してください。 – Alexis

+0

私はあなたのテストコードの目的を理解していないと述べなければならないでしょうが、マップサイズを変更しないと、仮想メモリを節約する別のチャンクではなく、とにかくそれを変える目的がどういうものか分かりません。 – EJP

+0

異なるマップサイズを使用しているときにファイルを読み込む効率にいくつかの影響があることを知りたいので、このコードを記述します。そして私は、1GBのファイルを読み込むかどうか、どのマップサイズを使うべきかを知りたい。 – Alexis

関連する問題