当您不断更改映射大小时,Java MappedByteBuffer性能会越来越差

当您不断更改映射大小时,Java MappedByteBuffer性能会越来越差,java,linux,nio,mappedbytebuffer,Java,Linux,Nio,Mappedbytebuffer,最近我做了一些关于Java MappedByteBuffer的测试。我发现,如果我不断地映射同一个文件并阅读它,那么花在阅读上的时间就会越来越长。但是如果我不改变地图大小,它将比我在地图大小变化测试中使用相同地图大小的速度更快 我有一个1GB的“数据文件”,里面装满了整数 private final File dataFile = new File("~/testfile"); private final int intNum = 1024 * 1024 * 1024 / 4; // 1GB I

最近我做了一些关于Java MappedByteBuffer的测试。我发现,如果我不断地映射同一个文件并阅读它,那么花在阅读上的时间就会越来越长。但是如果我不改变地图大小,它将比我在地图大小变化测试中使用相同地图大小的速度更快

我有一个1GB的“数据文件”,里面装满了整数

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();
} 
固定大小测试:

@Test
public void testBuffSizeReadPerformance2() throws Exception {
    System.out.println(ManagementFactory.getRuntimeMXBean().getName());

    for (int i = 0; i < 10; i++) {
        bufferSizePerformanceTest(1024 * 1024 * 1024);
    }
}
正如两个测试所显示的,在两个测试中,使用相同大小(1024MB)读取数据所花费的时间是非常不同的。固定大小的测试比变化测试快得多

我的问题是: 1.这是怎么发生的,为什么会更快? 2.MappedByteBuffer是否占用物理内存?正如我在ActivityMonitor中看到的,它不会占用物理内存

谢谢

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

释放缓冲区代码:

public static void releaseByteBuffer(ByteBuffer buffer) throws NoSuchFieldException, IllegalAccessException {
    Cleaner cleaner = ((DirectBuffer) buffer).cleaner();
    cleaner.clean();
}
我不认为这个问题的原因是内存使用。因为即使我打开发布代码和gc代码,它也有相同的输出。无论如何,如果是关于内存使用,我在第二个测试中将循环时间设置为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));
    }
}
输出:

16651@LiuzhMacbook.local
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

您没有“不断更改映射大小”。您一直在创建新映射,并且没有释放映射的机制,包括GC,因此您正在使用越来越多的内存

您应该尽可能少地使用
mappedbytebuffer
,这可能意味着您也需要将尺寸变大


我不知道ByteBufferUtil.releaseByteBuffer(buffer)是做什么的,也不知道它来自哪里,但这些东西的性质是不可靠的。

我必须声明我不理解您的测试代码的目的,但是,如果不更改映射大小,您可能总是得到相同的底层映射内存,而不是另一个块,从而节省了虚拟内存。我不知道更改它的目的是什么。我想知道当使用不同的映射大小时,是否会影响读取文件的效率,所以我编写了这段代码。我想知道如果我读取了1GB的文件,我应该使用什么样的映射大小。答案总是一样的。尽可能大。您的测试在同一进程内运行时会完全失效,因此您会得到各种进程内/缓存效果,这些效果不会在单独的进程中发生。这里的问题主要是你的测试方法,而不是结果。
14157@LiuzhMacbook.local
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
public static void releaseByteBuffer(ByteBuffer buffer) throws NoSuchFieldException, IllegalAccessException {
    Cleaner cleaner = ((DirectBuffer) buffer).cleaner();
    cleaner.clean();
}
@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));
    }
}
16651@LiuzhMacbook.local
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