With the release of the new open source project, Go-pmem-transaction, support for byte-addressable persistent memory with Go programming language is now available. Announced as early as 2015, persistent memory technology has started to appear in servers only recently. Persistent memory provides RAM-like access time with the added benefit of persistence. It offers huge potential to reduce the execution time and development efforts for applications that access large amounts of data. Furthermore, the time to recover from a crash can be vastly reduced, regardless of the size of the in-memory data set. This will change the way developers approach the problem of data availability.
With go-pmem (an extension to Go programming language) and go-pmem-transaction packages, we bring to developers the ability to write applications which can use persistent memory with Go.
Several applications like in-memory databases often work with hot data in RAM and have checkpointing code to periodically persist these changes to storage media. To do this, they go through file systems and marshal/unmarshal this data every time it is moved between RAM and storage media. This adds to the latency of operations, not to mention the various data consistency modes which are introduced as a result of the frequency of checkpointing. For applications working with GBs of data, this also means a crash is followed by minutes, often hours of recovery time to get the application to the pre-crash state with data back in RAM.
This is where persistent memory can help. With persistent memory, applications can read and write data at byte-level granularity with RAM-like access time and guaranteed persistence. But persistent memory provides its own set of challenges. Often, the application may desire to change a data structure in a transactional manner (i.e., a system crash in the middle should leave the structure as it was before the update began).
Without some level of support from the language, this can be a very onerous task. Many approaches have been suggested to provide accessibility to persistent memory to application developers [1, 2, 3]. These efforts usually provide ad hoc libraries OR change the language/compiler to access persistent memory. Ad hoc libraries often provide a difficult programming interface. As memory management for RAM has increasingly become a part of programming languages, we believe managing persistent memory should be addressed in the same manner. And so, our programming model includes changes to Go itself. We chose Go because it has low concurrency overheads and can support applications needing high storage (persistent memory) throughput.
In go-pmem, we add new keywords to the language and change the runtime of Go to work with persistent memory. With these changes, Go supports a dynamically-sized heap in persistent memory, and can garbage collect regions in persistent memory. We add pnew and pmake built-ins to Go, which are similar to new and make respectively, but for persistent memory. Because data written to persistent memory survives system crashes/power losses, it is important that changes be done in a crash-consistent manner. With the transaction package of go-pmem-transaction, we provide an undo and a redo logging library to do this.
Several months of discussion led us to our current programming model and we look forward to active engagement by the open source community as we continue to enhance and evolve this model.
To gain confidence in our changes, we decided to write a non-trivial application that would use go-pmem and go-pmem-transaction. We chose the open source Redis key value store due to its popularity. We have rewritten it in Go to use persistent memory freely. For example, we put the entire key value store in persistent memory. For comparison, we ran an unmodified version of Redis by placing the database in persistent memory and used the storage interface (block mode I/O) provided by the OS. We compared this with Go-Redis, where the database is also placed directly in persistent memory, and we use the language support in Go that we have implemented to access the persistent memory using simple loads/stores. Initial results show a speedup in crash recovery time of about 3x. It should be kept in mind that, unlike Redis, Go-Redis does not have explicit crash-recovery code in it! In the coming months, we are planning to open-source Go-Redis.
Our team is constantly working to increase the adoption of this technology in commercial applications and we look forward to the community’s contributions and insights. Tell us how you are using this new project and help us improve it. Stay tuned to the Open Source Blog and follow us on Twitter (@vmwopensource) for updates.