1 回答
TA贡献1851条经验 获得超4个赞
带有 FileInputStream 的 2MB 缓冲区可能不是最佳选择。有关详细信息,请参阅此问题。虽然它是在 Windows 上,但我在 Linux 上看到了类似的性能问题。根据操作系统的不同,分配一个临时的大缓冲区可能会导致额外的mmap
调用和随后的页面错误。如此大的缓冲区也使 L1/L2 缓存变得无用。
从常规文件中读取只会被短暂阻塞,并且不依赖于任何 Java 线程。
这并非总是如此。在您的基准测试中,文件显然缓存在操作系统页面缓存中,并且没有发生设备 I/O。访问真实硬件(尤其是旋转磁盘)可能要慢几个数量级。磁盘 I/O 的最坏时间是不完全可以预测的——它可以大到数百毫秒,这取决于硬件条件、I/O 队列的长度、调度策略等。
JNI 临界区的问题是每当发生延迟时,它可能会影响所有线程,而不仅仅是执行 I/O 的线程。这对于单线程应用程序来说不是问题,但这可能会导致多线程应用程序中出现不需要的 stop-the-world 暂停。
反对 JNI 的另一个关键原因是与 GCLocker 相关的 JVM 错误。有时它们可能会导致冗余的 GC 周期或忽略某些 GC 标志。以下是一些示例(仍未修复):
JDK-8048556不必要的 GCLocker 启动的年轻 GC
JDK-8057573如果 GCLocker 处于活动状态,则忽略 CMSScavengeBeforeRemark
JDK-8057586如果 GCLocker 处于活动状态,则忽略显式 GC
所以,问题是你关心的是吞吐量还是延迟。如果您只需要更高的吞吐量,JNI critical 可能是正确的选择。但是,如果您还关心可预测的延迟(不是平均延迟,而是 99.9%),那么 JNI critical 似乎不是一个好的选择。
添加回答
举报