#8 go-pmem: Native Support for Programming Persistent Memory in Go

18 Jun 2021

Link https://www.usenix.org/conference/atc20/presentation/george
Year USENIX 2020

Details

This paper proposes go-pmem, an extension of Go that natively support persistent memory programming. The authors were motivated to do this work when porting Redis to NVM platforms. The original Redis uses both DRAM and block storage to implement an in-memory database. The authors observed a speed up just by replacing the block storage with NVM, and a further speed up when using the NVM through the byte-addressable interface similar to DRAM (this eliminates the AOF, which is a log file Redis uses to achieve data persistency, since data is now directly persisted to NVM. One might call this a in-nvm database).

Goal 1 refers to the fact that the data’s location (DRAM or NVM) should not change its type (ex. persistent integer type). This enables goal 6, where functions can treat volatile and persistent objects in the same way. Goal 2 means that programmer should allocate persistent memory from persistent heap, which is separate from the volatile heap. Goal 3 says that persistent pointers should also use absolute addresses like volatile pointers. More on this later.

Why Native Go?

The authors argue that introducing persistent memory libraries exposes different programming models (true for PMDK) and makes memory management tricky (this is pretty vague). Thus, the authors chose to enable pmem programming natively. Furthermore, the authors argue that a language that supports NVM natively should allow persistent memory allocations on the heap and support garbage collection of persistent objects in the heap. This paper also attempts to make porting legacy code easier by 1) changing less code via ex. function reuse and 2) for code that must be modified, making the changes minimal and simple via ex. native programming model. The authors chose Go because it is a high level managed language. The pmem extension can then utilize existing features such as automatic memory management.

Programming Model

Figure 1 right highlights (<-) the differences between a pmem program and the normal volatile code (Go does look a lot nicer than C).

Figure 1: go-pmem design goals and example code snippet [1].

Runtime Design

To implement persistent pointers, go-pmem utilizes pointer swizzling, which fixes pointers when the NVM virtual memory mapping changes. This allows go-pmem to store direct pointers in persistent memory. In contrast, PMDK adopts fat pointers, which contains the object’s pool ID and offset within the pool. The authors argue that fat pointers are slow because dereferencing them requires a hashmap lookup (pool ID -> pool base address) and an addition. On the other hand, pointer swizzling is performed once per pmem initialization. Consequent dereferences can be performed in the same way as virtual address pointers. Pointer swizzling also enables function reuse.

go-pmem requires users to mark the start and end of transactions. go-pmem currently has somewhat poor transaction concurrency support. To ensure transaction isolation, go-pmem requires the user to use locks. Despite where exactly the lock is acquired/released, go-pmem forces the locks the be acquired and the start of the tranasction and released at the end. This limits concurrency between transactions with conflicting locks, as the transaction are forced to occur sequentially even if some locks can be released before the end of the transaction.

Skipping sections on heap sesign, post-crash restarting algorithm. Skipping Implementation entirely…

Nevermind, the pmem allocation optimization seems important. go-pmem somehow caches frequently allocated types to speed up further allocations of such objects. Not sure exactly how this works (see question 1). In the evaluation, go-pemem and Makalu show >10x speed up compared to pmdk on memory allocation intensive microbenchmark. This is because Makalu and go-pmem do not write to pmem for each new allocation, where as PMDK must perform all alloac and dealloc in a txn (see q1).

Thoughts and Comments

Questions

  1. I am not too sure what the authors mean by go-pmem and Makaly do not write to pmem for each new allocation. I also need to confirm that PMDK only allow pmem allocation and deallocation within transactions.

Sources

[1] USENIX. “USENIX ATC ‘20 - go-pmem: Native Support for Programming Persistent Memory in Go” [Video file]. Available: https://www.youtube.com/watch?v=swnvGt3GlK0&t=834s