OpenHFT / Java Lang从Apache 2.0库开始,提供Java Chronicle使用的低级功能,而无需持久存储到文件中。 这允许对数据进行可序列化和反序列化,以及对本机空间(堆外)中的内存的随机访问。它支持使用对象池写入和读取可枚举类型。 例如,在不创建对象的情况下编写和读取String(如果已将其池化)。 它还支持以二进制和文本形式写入和读取原始类型,而不会产生任何垃圾。 小消息可以在微秒内序列化和反序列化。
最近增加
Java Lang支持DirectStore,类似于ByteBuffer,但可以是任意大小(在大多数系统上,最大为40到48位)。它支持64位大小和偏移量。 它支持压缩类型和对象序列化。 它还支持线程安全功能,例如易失性读取,有序(惰性)写入,CAS操作以及将int(4字节)用作本机内存中的锁。
在Java中测试本机内存锁
该测试具有一个锁和一个可切换的值。 一个线程将值从0更改为1,另一个线程将其从1更改为0。这大约进行了2000万次,但运行时间更长
final DirectStore store1 = DirectStore.allocate(1L << 12);final int lockCount = 20 * 1000 * 1000;new Thread(new Runnable() {@Overridepublic void run() {manyToggles(store1, lockCount, 1, 0);}}).start();manyToggles(store1, lockCount, 0, 1);store1.free();
manyToggles方法更有趣。 请注意,将偏移量为0的4个字节用作锁定。 您可以通过这种方式在本机空间中安排任意数量的锁。 例如,您可能有固定长度的记录,并希望能够在更新或访问它们之前将其锁定。 您可以在记录的“开头”放置一个锁。
private void manyToggles(DirectStore store1, int lockCount, int from, int to) {long id = Thread.currentThread().getId();assertEquals(0, id >>> 24);System.out.println("Thread " + id);DirectBytes slice1 = store1.createSlice();for (int i = 0; i < lockCount; i++) {assertTrue(slice1.tryLockNanosInt(0L, 10 * 1000 * 1000));int toggle1 = slice1.readInt(4);if (toggle1 == from) {slice1.writeInt(4L, to);} else {i--;}slice1.unlockInt(0L);}}
DataStore的大小及其中的偏移量很长,因此您可以将连续的本机内存块分配到多个GB中,并根据需要进行访问。 在我的2.6 GHz i5笔记本电脑上,此测试获得以下输出
Contended lock rate was 9,096,824 per second
这看起来不错,但在激烈的争用中,可以保留一个线程。 这对于许多锁和较低的争用更为有用。 注意:如果我将超时时间从10毫秒降低到1毫秒,它最终将失败,这意味着有时需要花费超过1毫秒的时间才能获得锁定!
结论
Java Lang库正在采取步骤,使其更容易使用具有堆上可用功能的本机内存。 语言支持不是很好,但是如果需要存储128 GB的数据,则可以使用堆外内存获得更好的GC行为。
翻译自: https://www.javacodegeeks.com/2013/07/openhft-java-lang-project.html