The NVM Programming Model (NPM) is a set of specifications developed by the SNIA NVM Programming Technical Working Group that defines recommanded behavior between various user space and kernel components supporting storage-class memory.
Persistent memory differs from standard DRAM in a great number of ways. Unlike traditional volatile memory which receives an anonymous region of memory, regions of persistent memory are owned by certain applications - much like files on the hard drive. There is a need to keep track of which application has access to which region of the persistent memory which can remain beyond the lifetime of the program's execution. With the commercialization of new storage-class memory, it becomes necessary to formally define the semantics of working with persistent memory regions. The NVM Programming Model (NPM) addresses this by defining the formal semantics for working with such devices. The Storage Networking Industry Association (SNIA) Technical Working Group (TWG) is the group heading the specification of the persistent memory programming model.
NPM defines the semantics for a persistent memory-aware file system. The model uses the same standard file semantics the industry has been using for 30-some years and apply it to persistent memory, providing it with the necessary facilities for managing permissions, as well as reading and writing block storage.
|Basic File APIs|
Additionally, there is also support for mapping memory regions to applications, providing an even more efficient way of accessing persistent memory storage. This feature is also known as direct access or DAX (note the term is used by both Linux and Windows). Memory-mapping a file can only be done once the file has already been created/opened, thereby already undergone the necessary permission checks. Memory-mapping a persistent file is done using the same function calls that already exist on both Windows and Linux. From the software point of view, the storage new becomes byte-addressable storage.
|Memory-mapped file APIs|
Traditional file I/O operates on block storage. Reading a single byte from a file involves reading an entire block (typically around 4 KiB in size). Likewise, flushing the data back to persistence, the full block has to be written out. With a persistent memory-aware file system, although the API remains the same, the operating system is aware of the persistent memory device and allows for direct byte-level access with the NVDIMM instead of block-level accesses.
The quickest way to do this is by simply calling
mmap() which will provide the program with direct load/store accesses. No context switching or interrupts are needed for those accesses. It's worth noting that a small caveat to this is that the system is not required to write the modifications back immediately.
To ease software support as well as to reduce code overhead required to take advantage of the persistent memory, NPM introduced the optional support for Optimized Flush, an ability for software to flush persistence directly from userspace, without intervening the kernel. Companies such as Intel support this through the introduction of new flushing instructions (e.g., see x86's persistent memory extensions).
- Intel's Persistent Memory Development Kit (PMDK)