Значения хроники: какой смысл, если ему все еще нужно выделить экземпляр в куче?
У меня возникли проблемы с пониманием того, как правильно использовать эту библиотеку, потому что она создает мусор при распределении, и это, кажется, намерение? Предназначена ли библиотека для использования с этими характеристиками? Или я что-то упускаю, и есть ли другой способ выделить?
Например:
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, 0, 4);
}
}
}
После профилирования в YourKit вы можете увидеть, что создается много аллокаций (мусора):
1 ответ
Вам нужно создать хотя бы один экземпляр в куче.
Однако, как только вы это сделаете, его можно будет использовать как вспомогательное средство, указывающее на любую область собственной памяти.
В этом примере данные во много раз превышают размер кучи, но не используют кучи.
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, i * Integer.BYTES, 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, 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, i * Integer.BYTES, Integer.BYTES);
boolean set = value.compareAndSwapValue(i, 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 наносекунд, чтобы записать данные в файл и прочитать их позже.