Chronicle Values:如果它仍然需要在堆上分配一个实例有什么意义?

问题描述

我在理解如何正确使用这个库时遇到了麻烦,因为它每次分配都会产生垃圾,而这似乎是我们的意图?该库是否旨在与这些特性一起使用?还是我遗漏了什么,还有其他分配方式吗?

例如:

package org.jire;

import net.openhft.chronicle.bytes.Byteable;
import net.openhft.chronicle.bytes.NativeBytesstore;
import net.openhft.chronicle.core.values.IntValue;
import net.openhft.chronicle.values.Values;

public class Test {
    public static void main(String[] args) {
        NativeBytesstore<Void> store = NativeBytesstore.nativeStoreWithFixedCapacity(4);
        while (true) {
            IntValue value = Values.newNativeReference(IntValue.class);
            ((Byteable) value).bytesstore(store,4);
        }
    }
}

yourkit 中被分析后,你可以看到有很多分配(垃圾)正在产生:

YourKit Profiling

解决方法

您需要在堆上至少创建一个实例。

然而,一旦你这样做了,它就可以用作指向本机内存中任何区域的享元。

在这个例子中,数据是堆大小的许多倍,但没有使用堆。

import net.openhft.chronicle.bytes.Byteable;
import net.openhft.chronicle.bytes.NativeBytesStore;
import net.openhft.chronicle.core.values.IntValue;
import net.openhft.chronicle.values.Values;

public class Test {
    public static void main(String[] args) {
        System.out.println("Run with -Xmx64m -verbose:gc -ea");
        int size = 250_000_000;
        IntValue value = Values.newNativeReference(IntValue.class);
        Byteable valuePtr = (Byteable) value;
        // NOTE: This is much,much larger than the heap size
        NativeBytesStore<Void> store = NativeBytesStore.nativeStoreWithFixedCapacity(size * Integer.BYTES);

        for (long t = 1; ; t++) {
            // set all the values
            for (int i = 0; i < size; i++) {
                valuePtr.bytesStore(store,i * Integer.BYTES,Integer.BYTES);
                boolean set = value.compareAndSwapValue(0,i);
                assert set;
            }
            System.out.print("set " + t * size + ",");

            // check and unset all the values
            for (int i = 0; i < size; i++) {
                valuePtr.bytesStore(store,Integer.BYTES);
                boolean set = value.compareAndSwapValue(i,0);
                assert set;
            }
            System.out.println("unset " + t * size);
        }
    }
}

使用 -Xmx64m -verbose:gc -ea 运行会在启动时打印一些 GC,但在运行时不会产生任何对象。

Run with -Xmx64m -verbose:gc -ea
[main] INFO net.openhft.chronicle.core.Jvm - Chronicle core loaded from file:/C:/cygwin64/home/peter/Build-All/Chronicle-Core/target/classes/
[GC (Allocation Failure)  16384K->2072K(62976K),0.0016387 secs]
[GC (Allocation Failure)  18456K->2376K(62976K),0.0016103 secs]
[GC (Allocation Failure)  18760K->5979K(62976K),0.0039673 secs]
[GC (Allocation Failure)  22363K->9703K(62976K),0.0152631 secs]
set 250000000,unset 250000000
set 500000000,unset 500000000
set 750000000,unset 750000000
set 1000000000,unset 1000000000
set 1250000000,unset 1250000000
set 1500000000,unset 1500000000
set 1750000000,unset 1750000000
set 2000000000,unset 2000000000
set 2250000000,unset 2250000000
set 2500000000,unset 2500000000
set 2750000000,unset 2750000000
set 3000000000,unset 3000000000
set 3250000000,unset 3250000000
set 3500000000,unset 3500000000
set 3750000000,unset 3750000000
set 4000000000,unset 4000000000
set 4250000000,unset 4250000000
set 4500000000,unset 4500000000
set 4750000000,unset 4750000000
set 5000000000,unset 5000000000

现在,为了真正有趣,您现在可以将其映射到一个文件,该文件可以被多个进程同时访问。

import net.openhft.chronicle.bytes.*;
import net.openhft.chronicle.core.values.IntValue;
import net.openhft.chronicle.values.Values;

import java.io.File;
import java.io.FileNotFoundException;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
        System.out.println("Run with -Xmx64m -verbose:gc -ea");
        int size = 250_000_000;
        IntValue value = Values.newNativeReference(IntValue.class);
        Byteable valuePtr = (Byteable) value;
        // NOTE: This is much,much larger than the heap size
        File deleteme = new File("deleteme");
        deleteme.delete(); // has to delete or there will be some data later.
        BytesStore store = MappedBytes.mappedBytes(deleteme,size * Integer.BYTES);

        for (long t = 1; ; t++) {
            long start = System.nanoTime();
            // set all the values
            for (int i = 0; i < size; i++) {
                valuePtr.bytesStore(store,0);
                assert set;
            }
            System.out.print("unset " + t * size);
            long time = (System.nanoTime() - start) / size;
            System.out.println(",avg time " + time+ " ns to set/unset.");
        }
    }
}

印刷品

Run with -Xmx64m -verbose:gc -ea
[main] INFO net.openhft.chronicle.core.Jvm - Chronicle core loaded from file:/C:/cygwin64/home/peter/Build-All/Chronicle-Core/target/classes/
[GC (Allocation Failure)  16384K->2072K(62976K),0.0014760 secs]
[GC (Allocation Failure)  18456K->2392K(62976K),0.0021388 secs]
[GC (Allocation Failure)  18722K->5839K(62976K),0.0043109 secs]
[GC (Allocation Failure)  22223K->9738K(62976K),0.0052064 secs]
[main] INFO net.openhft.chronicle.bytes.MappedFile - Took 8506 us to grow file deleteme
[main] INFO net.openhft.chronicle.bytes.MappedFile - Took 17 ms to add mapping for deleteme
set 250000000,unset 250000000,avg time 14 ns to set/unset.
set 500000000,unset 500000000,avg time 12 ns to set/unset.
set 750000000,unset 750000000,avg time 13 ns to set/unset.
set 1000000000,unset 1000000000,avg time 13 ns to set/unset.
set 1250000000,unset 1250000000,avg time 13 ns to set/unset.
set 1500000000,unset 1500000000,avg time 12 ns to set/unset.
set 1750000000,unset 1750000000,avg time 12 ns to set/unset.
set 2000000000,unset 2000000000,avg time 13 ns to set/unset.
set 2250000000,unset 2250000000,avg time 12 ns to set/unset.
set 2500000000,unset 2500000000,avg time 12 ns to set/unset.
set 2750000000,unset 2750000000,avg time 12 ns to set/unset.
set 3000000000,unset 3000000000,avg time 13 ns to set/unset.
set 3250000000,unset 3250000000,avg time 13 ns to set/unset.
set 3500000000,unset 3500000000,avg time 13 ns to set/unset.
set 3750000000,unset 3750000000,avg time 13 ns to set/unset.
set 4000000000,unset 4000000000,avg time 13 ns to set/unset.
set 4250000000,unset 4250000000,avg time 13 ns to set/unset.
set 4500000000,unset 4500000000,avg time 13 ns to set/unset.
set 4750000000,unset 4750000000,avg time 12 ns to set/unset.
set 5000000000,unset 5000000000,avg time 12 ns to set/unset.

注意:将数据写入文件并稍后读回平均只需 13 纳秒。