27

メモリバリアは、データキャッシュの一貫性を保証します。ただし、TLBの一貫性が保証されますか?

スレッド間でMappedByteBufferを渡すときに、JVM(java 7 update 1)がメモリエラー(SIGBUS、SIGSEG)でクラッシュすることがあるという問題が発生しています。

例えば

final AtomicReference<MappedByteBuffer> mbbQueue = new AtomicReference<>();

// in a background thread.
MappedByteBuffer map = raf.map(MapMode.READ_WRITE, offset, allocationSize);
Thread.yield();
while (!inQueue.compareAndSet(null, map));


// the main thread. (more than 10x faster than using map() in the same thread)
MappedByteBuffer mbb = inQueue.getAndSet(null);

Thread.yield()がないと、force()、put()、およびCのmemcpy()でクラッシュが発生することがあります。これらはすべて、メモリに不正にアクセスしようとしていることを示しています。Thread.yield()を使用しても問題はありませんが、信頼できる解決策のようには思えません。

誰かがこの問題に遭遇しましたか?TLBとメモリバリアについての保証はありますか?


編集:OSはCentos 5.7ですが、i7およびDualXeonマシンでの動作を確認しました。

なぜ私はこれをするのですか?メッセージの書き込みにかかる平均時間は長さにもよりますが35〜100 nsであり、プレーンなwrite()の使用はそれほど高速ではないためです。現在のスレッドでメモリマップとクリーンアップを行う場合、これには50〜130マイクロ秒かかります。バックグラウンドスレッドを使用すると、メインスレッドがバッファを交換するのに約3〜5マイクロ秒かかります。なぜバッファを交換する必要があるのですか?私は多くのGBのデータを書き込んでおり、ByteBufferのサイズを2GB以上にすることはできないためです。

4

1 に答える 1

13

マッピングはmmap64(FileChannel.map)を介して行われます。アドレスにアクセスすると、ページフォールトが発生し、カーネルがそこで読み取り/書き込みを行います。mmap中にTLBを更新する必要はありません。

(すべてのCPUの)TLBは、MappedByteBufferのファイナライズによって処理されるmunmap中に検証されないため、munmapにはコストがかかります。

マッピングには多くの同期が含まれるため、アドレス値が破損することはありません。

Unsafeを介して派手なものを試すチャンスはありますか?

于 2011-11-30T17:00:42.103 に答える