File(s): | GitHub* |
License: | BSD 3-clause |
Optimized for... | |
---|---|
Operating System: | Linux* kernel version 4.3 or higher |
Hardware: | Emulated: See Emulated: See How to Emulate Persistent Memory Using Dynamic Random-access Memory (DRAM) |
Software: (Programming Language, tool, IDE, Framework) |
LLPL for Java*, Persistent Memory Development Kit (PMDK) libraries |
Prerequisites: | Familiarity with Java* |
Introduction
Create a "Hello World" program with key methods in the Low Level Persistence Library (LLPL) for Java*. Learn how to use persistent memory blocks, including heap allocation, Flushable.class, heap setRoot, heap copyFromArray, and heap copyToArray methods. The sample writes a "Hello..." message to persistent memory or reads it back with a console notification, depending on user input. You can try this code sample using Intel® Optane™ DC persistent memory, or with persistent memory emulation using DRAM.
Prerequisites
The article assumes that you have a basic understanding of persistent memory concepts and are familiar with the features of the PMDK. If not, visit the Intel® Developer Zone’s Persistent Memory site, where you’ll find the information you need to get started.
Code Sample Design
The sample creates a persistent memory heap (or pool in PMDK terminology) where it stores the "Hello…" message. The write_hello_string method stores the "Hello…" message to the heap and the read_hello_string method reads the message back from the heap. See the code snippet below for more details. Depending on the option passed in at execution time ("R" for read or "W" for write), the code sample performs a read from or a write to the persistent memory heap. Option "Q" is used to exit the program.
Data Structures
The heap object is the primary data structure for the "Hello" program. It represents the persistent memory available to the program which, underneath, is a memory mapped file residing on a persistent memory-aware file system.
Figure 1. A high-level overview of the persistent memory heap used to hold the "Hello..." string
A Code Walk-Through
Starting in the main program, two variables are defined: a "Heap h" and a "String msg." To get an instance of a heap object, a call is made to the getHeap() method with the location of the file to be memory mapped. If the file does not exist, it is created. The string msg is initialized to "Hello Persistent Memory!!!" and also converted to a byte array. This array will be needed later to write the string to persistent memory.
Next, the program parses command line input to determine whether to read from or write to persistent memory.
The Write Option
When starting the program, the user is prompted to select one of the options. When directed by option "W" to write to persistent memory, the sample uses multiple methods to carry out the task. See the code snippet below for more details:
Step 1: Allocate Persistent Memory
The h.allocateMemoryBlock method allocates persistent memory. It requires two parameters:
- Size – the number of blocks to allocate
- Boolean value - true means that the allocation should be done transactionally
Step 2: Get the root object
The h.setRoot method sets the root address for the root block in heap h.
Step 3: Write the "Hello…" message to persistent memory
The h.copyFromArray copies the provided byte array to persistent memory. It requires four parameters:
- Source – the input array
- Source offset – byte offset from the beginning of the source
- Destination offset – byte offset from the beginning of the destination block
- Size – the number of bytes to be copied
Step 4: Flush the data in cache to persistent memory
In this step the newBlock.flush method ensures that the input array flushes any CPU cache lines holding any part of the modified block.
Step 5: Output to console, confirming a successful write
The Read Option
The "R" option reads the persistent memory. See the code snippet below for more details:
Step 1: Allocate a new byte array to read the data from persistent memory
Step 2: Get the address for the root block
The h.getRoot() method returns the address from the root block, which can be used to recreate the MemoryBlock reference object.
Step 3: Recreate reference object newBlock from a persistent memory address
To access the persistent memory block, we need a point of reference. It will be an object of class MemoryBlock<>, which is recreated from a persistent memory address using the h.memoryBlockFromHandle() method. No new persistent memory is allocated in this call.
Step 4: Read the "Hello…" message
The newBlock.copyToArray method copies a byte array to persistent memory. It requires four parameters:
- Source offset – byte offset from the beginning of the source
- Destination – new byte output array
- Destination offset – byte offset from the beginning of the destination block
- Size – the number of bytes to be copied
Step 5: Output to console, confirming a successful read
Compile and Run
A Makefile is included to help you compile and build the binary.
Running ‘make’ compiles the application in the current working directory:
See below for an example of the run after building the binary:
Summary
The "Hello…" sample code described in this article demonstrates the usage of the several LLPL methods, including allocating persistent memory blocks, flushing the data to persistent memory, and copying to and from persistent memory using LLPL. Build and run the code sample included with this article and find more persistent memory programming examples in the PMDK examples folder in our GitHub* repository.
To learn more about LLPL read Introducing the Low Level Persistent Library (LLPL) for Java*.
About the Author
Thai Le is the software engineer focusing on cloud computing and performance computing analysis at Intel Corporation.
Steven Briscoe is an Industry Technical Specialist driving the adoption of Persistent Memory with Cloud Service Providers at Intel Corporation.