OpenHFT / Java Lang начинался как библиотека Apache 2.0 для обеспечения низкоуровневой функциональности, используемой Java Chronicle, без необходимости сохранения в файле. Это обеспечивает сериализацию и десериализацию данных и произвольный доступ к памяти в собственном пространстве (вне кучи). Поддерживает запись и чтение перечислимых типов с пулами объектов. например, написание и чтение строки без создания объекта (если он был объединен). Он также поддерживает запись и чтение примитивных типов в двоичном и текстовом формате без создания мусора. Маленькие сообщения могут быть сериализованы и десериализованы за микросекунды.
Недавние добавления
Java Lang поддерживает DirectStore, который похож на ByteBuffer, но может быть любого размера (от 40 до 48 бит в большинстве систем). Он поддерживает 64-битные размеры и смещение. Он поддерживает сжатые типы и сериализацию объектов. Он также поддерживает функции безопасности потоков, такие как энергозависимые чтения, упорядоченные (ленивые) записи, операции CAS и использование int (4 байта) в качестве блокировки в собственной памяти.
Тестирование встроенной блокировки памяти в Java
Этот тест имеет одну блокировку и значение, которое переключается. Один поток изменяет значение с 0 на 1, а другой переключает его с 1 на 0. Это происходит около 20 миллионов раз, но работает дольше
01
02
03
04
05
06
07
08
09
10
11
12
|
final DirectStore store1 = DirectStore.allocate(1L << 12 ); final int lockCount = 20 * 1000 * 1000 ; new Thread( new Runnable() { @Override public void run() { manyToggles(store1, lockCount, 1 , 0 ); } }).start(); manyToggles(store1, lockCount, 0 , 1 ); store1.free(); |
Метод manyToggles более интересен. Примечание использует 4 байта со смещением 0 в качестве блокировки. Таким способом вы можете расположить любое количество замков в родном пространстве. Например, у вас могут быть записи фиксированной длины, и вы хотите иметь возможность заблокировать их перед обновлением или получить к ним доступ. Вы можете поставить блокировку на «голову» записи.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
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); } } |
Размер хранилища данных и смещений в нем велики, что позволяет выделять непрерывный блок собственной памяти во многие ГБ и получать к нему доступ по мере необходимости. На моем ноутбуке i5 с частотой 2,6 ГГц я получаю следующий вывод для этого теста
1
|
Contended lock rate was 9 , 096 , 824 per second |
Это выглядит великолепно, но в условиях сильной конкуренции одна нить может быть предотвращена. Это более полезно для большого количества блокировок и меньшей конкуренции. Примечание: если я уменьшу тайм-аут с 10 мс до 1 мс, это в конечном итоге завершится неудачей, означая, что иногда для блокировки требуется более 1 мс!
Вывод
Библиотека Java Lang делает шаг к упрощению использования встроенной памяти с той же функциональностью, что и в куче. Языковая поддержка не так хороша, но если вам нужно сохранить, скажем, 128 ГБ данных, вы получите намного лучшее поведение GC, используя не кучу памяти.