56
responsibility to design in a strategy to maintain consistent data structures on storage,
both at runtime and when recovering from application and system crashes.
Unlike storage-resident data structures, application developers are concerned
about maintaining consistency of memory-resident data structures at runtime. When
an application has multiple threads accessing the same data structure, techniques like
locking are used so that one thread can perform complex changes to a data structure
without another thread seeing only part of the change. When an application exits or
crashes, or the system crashes, the memory contents are gone, so there is no need
to maintain consistency of memory-resident data structures between runs of an
application like there is with storage-resident data structures.
These explanations may seem obvious, but these assumptions that the storage state
stays around between runs and memory contents are volatile are so fundamental in
the way applications are developed that most developers don’t give it much thought.
What’s different about persistent memory is, of course, that it is persistent, so all the
considerations of both storage and memory apply. The application is responsible for
maintaining consistent data structures between runs and reboots, as well as the threadsafe locking used with memory-resident data structures.
If persistent memory has these attributes and requirements just like storage, why
not use code developed over the years for storage? This approach does work; using the
storage APIs on persistent memory is part of the programming model we described
in Chapter 3. If the existing storage APIs on persistent memory are fast enough and
meet the application’s needs, then no further work is necessary. But to fully leverage
the advantages of persistent memory, where data structures are read and written in
place on persistence and accesses happen at the byte granularity, instead of using the
block storage stack, applications will want to memory map it and access it directly. This
eliminates the buffer-based storage APIs in the data path.
Atomic Updates
Each platform supporting persistent memory will have a set of native memory
operations that are atomic. On Intel hardware, the atomic persistent store is 8 bytes.
Thus, if the program or system crashes while an aligned 8-byte store to persistent
memory is in-flight, on recovery those 8 bytes will either contain the old contents or
the new contents. The Intel processor has instructions that store more than 8 bytes,
but those are not failure atomic, so they can be torn by events like a power failure.
Chapter 4 Fundamental ConCepts oF persistent memory programming
responsibility to design in a strategy to maintain consistent data structures on storage,
both at runtime and when recovering from application and system crashes.
Unlike storage-resident data structures, application developers are concerned
about maintaining consistency of memory-resident data structures at runtime. When
an application has multiple threads accessing the same data structure, techniques like
locking are used so that one thread can perform complex changes to a data structure
without another thread seeing only part of the change. When an application exits or
crashes, or the system crashes, the memory contents are gone, so there is no need
to maintain consistency of memory-resident data structures between runs of an
application like there is with storage-resident data structures.
These explanations may seem obvious, but these assumptions that the storage state
stays around between runs and memory contents are volatile are so fundamental in
the way applications are developed that most developers don’t give it much thought.
What’s different about persistent memory is, of course, that it is persistent, so all the
considerations of both storage and memory apply. The application is responsible for
maintaining consistent data structures between runs and reboots, as well as the threadsafe locking used with memory-resident data structures.
If persistent memory has these attributes and requirements just like storage, why
not use code developed over the years for storage? This approach does work; using the
storage APIs on persistent memory is part of the programming model we described
in Chapter 3. If the existing storage APIs on persistent memory are fast enough and
meet the application’s needs, then no further work is necessary. But to fully leverage
the advantages of persistent memory, where data structures are read and written in
place on persistence and accesses happen at the byte granularity, instead of using the
block storage stack, applications will want to memory map it and access it directly. This
eliminates the buffer-based storage APIs in the data path.
Atomic Updates
Each platform supporting persistent memory will have a set of native memory
operations that are atomic. On Intel hardware, the atomic persistent store is 8 bytes.
Thus, if the program or system crashes while an aligned 8-byte store to persistent
memory is in-flight, on recovery those 8 bytes will either contain the old contents or
the new contents. The Intel processor has instructions that store more than 8 bytes,
but those are not failure atomic, so they can be torn by events like a power failure.
Chapter 4 Fundamental ConCepts oF persistent memory programming
