Programming Persistent Memory With Java

Introduction

Intel has taken persistent memory programming with Java to the next level with the 1.0 release of the Low Level Persistent Library (LLPL) for Java. LLPL is an open source Java library that gives Java developers access to persistent memory in a fast and flexible way. LLPL adds to the many other resources for persistent memory programming and is part of the Persistent Memory Development Kit (PMDK). PMDK, though maintained by Intel, is based on (Storage Networking Industry Association) SNIA industry standards. In addition to being part of PMDK, LLPL depends on two PMDK libraries, libpmem and libpmemobj. LLPL aims to provide flexible, high-performance access to persistent memory from Java with things like heaps, memory blocks, and transactions. 

This article introduces some of the new concepts of LLPL and links to examples and resources to learn more. The concepts discussed in this article build upon persistent memory programming foundations such as transactions and flushing. For a refresher on those concepts, check out our Quick Start Guide, or chapter 7 of Programming Persistent Memory, A Comprehensive Guide for Developers, which is available for purchase or free download. 

Heaps, Memory Blocks, and Transactions

An LLPL heap is a pool of persistent memory and an allocator for it. You can create LLPL heaps, reopen them, and delete them. You can create many heaps of almost any size, as long as there is unused persistent memory available to create them. Unlike Java heaps, LLPL heaps are persistent, so even after a restart, you can access the heap and their memory blocks. Additionally, the heap API is thread-safe.

When you allocate memory in LLPL, what you get back is a MemoryBlock object, which provides an accessor API for the allocation. 

To create a heap and allocate memory block:

Heap heap = Heap.createHeap("/pmem/heap1", 100 * 1024 * 1024);
MemoryBlock block1 = heap.allocateMemoryBlock(1024, false);

In Java, garbage collection will automatically deallocate unreachable memory, but in LLPL, you must call the MemoryBlock free()method to deallocate memory manually.

The MemoryBlock API provides low-level setter and getter methods. Locations within a memory block to write or read are specified using a zero-based long offset from the beginning of the block. The MemoryBlock API does no locking, so developers have the freedom to create whatever concurrency scheme appropriate for their application.

You can ask a memory block for its numeric name, known as its "handle," and write this Java long handle into other memory blocks. Using a handle allows blocks to be linked, supporting the implementation of efficient reference-based data structures. Memory block handles remain valid until the block's memory is freed.

Transactions in LLPL, just like in the PMDK libpmemobj library, allow for creating fail-safe writes within an atomic aggregate. LLPL heap modifications (e.g. writes, allocations) done in a transaction behave as if they all executed together or didn't execute at all. The LLPL Transaction API integrates well with Java's exception handling and uses Java lambdas as transaction bodies. 

String s = "Saturn";
Transaction.create(heap, () -> {
   block1.addToTransaction(0, Integer.BYTES + s.length());
   block1.setInt(0, s.length());
   block1.copyFromArray(s.getBytes(), 0, 4, s.length());
});

Summary

This article highlights three primary elements of the new 1.0 release of LLPL: heaps, memory blocks, and transactions. LLPL is compatible with the Java Development Kit (JDK) 8 and higher and supports building with Maven or Make. The availability of LLPL on MavenCentral is in-progress. To learn more about LLPL, please check out the webinar, Java Programming with Persistent Memory.

Resources 

Book: Programming Persistent Memory
Webinar Programming with Persistent Memory from Java
More details about 1.0 release of LLPL on pmem.io
LLPL on GitHub
Cassandra PMEM examples on GitHub

Información sobre productos y desempeño

1

Los compiladores Intel pueden o no optimizar al mismo nivel para los microprocesadores que no son Intel en optimizaciones que no son exclusivas de los microprocesadores Intel. Estas optimizaciones incluyen los conjuntos de instrucciones SSE2, SSE3 y SSSE3, y otras optimizaciones. Intel no garantiza la disponibilidad, funcionalidad o eficacia de ninguna optimización en microprocesadores que no sean fabricados por Intel. Las optimizaciones dependientes del microprocesador en este producto fueron diseñadas para usarse con microprocesadores Intel. Ciertas optimizaciones no específicas de la microarquitectura Intel se reservan para los microprocesadores Intel. Consulte las guías de referencia y para el usuario para obtener más información acerca de los conjuntos de instrucciones específicos cubiertos por este aviso.

Revisión del aviso n.° 20110804