私は、ダイレクト バイト バッファで最適に機能するいくつかの -to- コードに取り組んでいます - 長寿命で大きい (1 接続あたり数十から数百メガバイト) SocketChannel
。対パフォーマンスのベンチマーク。SocketChannel
FileChannel
ByteBuffer.allocate()
ByteBuffer.allocateDirect()
その結果には、うまく説明できない驚きがありました。以下のグラフでは、256KB と 512KB でByteBuffer.allocate()
転送実装の非常に顕著な崖があり、パフォーマンスは最大 50% 低下しています。のパフォーマンスの崖も小さいようですByteBuffer.allocateDirect()
。(%-gain シリーズは、これらの変化を視覚化するのに役立ちます。)
バッファ サイズ (バイト) と時間 (MS)
ByteBuffer.allocate()
との間の奇妙な性能曲線の差はなぜByteBuffer.allocateDirect()
ですか? カーテンの後ろで何が起こっているのですか?
ハードウェアとOSに依存する可能性が非常に高いため、詳細は次のとおりです。
- デュアルコア Core 2 CPU を搭載した MacBook Pro
- インテル X25M SSD ドライブ
- OS X 10.6.4
ソースコード、ご要望に応じて:
package ch.dietpizza.bench;
import static java.lang.String.format;
import static java.lang.System.out;
import static java.nio.ByteBuffer.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public class SocketChannelByteBufferExample {
private static WritableByteChannel target;
private static ReadableByteChannel source;
private static ByteBuffer buffer;
public static void main(String[] args) throws IOException, InterruptedException {
long timeDirect;
long normal;
out.println("start");
for (int i = 512; i <= 1024 * 1024 * 64; i *= 2) {
buffer = allocateDirect(i);
timeDirect = copyShortest();
buffer = allocate(i);
normal = copyShortest();
out.println(format("%d, %d, %d", i, normal, timeDirect));
}
out.println("stop");
}
private static long copyShortest() throws IOException, InterruptedException {
int result = 0;
for (int i = 0; i < 100; i++) {
int single = copyOnce();
result = (i == 0) ? single : Math.min(result, single);
}
return result;
}
private static int copyOnce() throws IOException, InterruptedException {
initialize();
long start = System.currentTimeMillis();
while (source.read(buffer)!= -1) {
buffer.flip();
target.write(buffer);
buffer.clear(); //pos = 0, limit = capacity
}
long time = System.currentTimeMillis() - start;
rest();
return (int)time;
}
private static void initialize() throws UnknownHostException, IOException {
InputStream is = new FileInputStream(new File("/Users/stu/temp/robyn.in"));//315 MB file
OutputStream os = new FileOutputStream(new File("/dev/null"));
target = Channels.newChannel(os);
source = Channels.newChannel(is);
}
private static void rest() throws InterruptedException {
System.gc();
Thread.sleep(200);
}
}