Статьи

OpenHFT Java Lang проект

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, используя не кучу памяти.

Ссылка: проект OpenHFT Java Lang от нашего партнера JCG Питера Лоури из блога Vanilla Java .