当前位置:  开发笔记 > 编程语言 > 正文

记忆障碍和TLB

如何解决《记忆障碍和TLB》经验,为你挑选了1个好方法。

内存障碍保证数据缓存一致.但是,它是否保证TLB一致?

我看到一个问题,当在线程之间传递MappedByteBuffer时,JVM(java 7更新1)有时会因内存错误(SIGBUS,SIGSEG)而崩溃.

例如

final AtomicReference 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和内存障碍的保证吗?


编辑:操作系统是Centos 5.7,我已经看到了i7和双Xeon机器上的行为.

为什么我这样做?因为写入消息的平均时间是35-100 ns,具体取决于长度,使用普通的write()并不是那么快.如果我在当前线程中进行内存映射和清理,则需要50-130微秒,使用后台线程执行此操作需要大约3-5微秒的主线程交换缓冲区.为什么我需要交换缓冲区呢?因为我写的是很多GB数据而且ByteBuffer的大小不能超过2 GB.



1> bestsss..:

映射是通过mmap64(FileChannel.map)完成的.访问地址时会出现页面错误,内核将为您读取/写入.在mmap期间不需要更新TLB.

TLB(所有cpus)在munmap期间未经验证,由mappedByteBuffer的最终化处理,因此munmap成本很高.

映射涉及大量同步,因此地址值不会被破坏.

你有没有机会通过Unsafe尝试花哨的东西?


@Peter,顺便说一句,你在清理之前不需要强制(unmap).你告诉过你正试图将它用作进程间通信,而你只是在写作方面遇到问题.TLB无关紧要,毕竟它是一个缓存,内核处理页面错误(并更新TLB)
这是你的问题......你正在取消所有引用的去除:SIGSEV的主要原因.如果你想使用它,将ByteBuffer包装成带有ref/ref的引用,并确保你支持它.
手动取消映射可能不会超高效,因为它会刷新所有CPU的TLB.当由GC执行时,它通常是大量的[即队列中的多个清洁器]并且效果较小,当然当调用清洁器是另一个令人不快的故事时.
推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有