Key/Value Store for Persistent Memory Rob Dickinson -- pmemkv Technical Lead Agenda

• Why pmemkv? • Key/Value API • Language Bindings • Storage Engines • Roadmap

SPDK, PMDK & Vtune™ Summit 2 why pmemkv?

Persistent memory programming is difficult There are many languages in the cloud Key/value datastores are increasingly popular

→ Large addressable market of cloud developers for an easy KV store for persistent memory

SPDK, PMDK & Vtune™ Summit 3 goals for pmemkv

Technical: Community: Local key/value store (no networking) Open source, developed in the open Idiomatic language bindings Friendly licensing Simple, familiar, bulletproof API Outside contributions are welcome Easily extended with new engines Collaboration alternative for folks frustrated with other OS projects Optimized for persistent memory (limit copying to/from DRAM) Intel provides stewardship, validation on real hardware, and code reviews Flexible configuration, not limited to a single storage algorithm Standard/comparable benchmarks

SPDK, PMDK & Vtune™ Summit 4 simple & portable key/value API

Engine Lifecycle: Start ( engine_name, json_config ) → engine Stop ( engine )

Engine Operations: Iteration Operations: (optional) engine.Put ( key, value ) engine.Count ( ) → count engine.Get ( key, value_or_callback ) engine.All ( key_callback ) engine.Exists ( key ) → true/false engine.Each ( key_and_value_callback ) engine.Remove ( key ) plus range iteration versions of these!

SPDK, PMDK & Vtune™ Summit 5 pmemkv sample program -- C++

int main() { KVEngine* kv = KVEngine::Start("vsmap", "{\"path\":\"/dev/shm/\"}");

KVStatus s = kv->Put("key1", "value1"); assert(s == OK && kv->Count() == 1);

string value; s = kv->Get("key1", &value); assert(s == OK && value == "value1");

kv->All([](const string& k) { LOG(" visited: " << k); });

s = kv->Remove("key1"); assert(s == OK && !kv->Exists("key1"));

delete kv; return 0; }

SPDK, PMDK & Vtune™ Summit 6 Idiomatic LANGUAGE BINDINGS

Implementations: Goals: C++ (core) No modifications to languages or runtime environments C (extern "C" on C++ core) Designed for multi-language use Java (v8 or higher) Familiar object model NodeJS (v6.10 or higher) Familiar error handling Ruby (v2.2 or higher) Language-specific types Python (coming soon!) Heap offloading (where applicable) Consistent unit tests

SPDK, PMDK & Vtune™ Summit 7 pmemkv sample program -- JAVA

public static void main(String[] args) { KVEngine kv = new KVEngine("vsmap", "{\"path\":\"/dev/shm/\"}");

kv.put("key1", "value1"); assert kv.count() == 1;

assert kv.get("key1").equals("value1");

kv.all((String k) -> System.out.println(" visited: " + k));

kv.remove("key1"); assert !kv.exists("key1"); NOTE: kv.stop(); Binding based on JNI } Throw exception on error Supports String, byte[] and ByteBuffer Overloaded iterator methods/types

SPDK, PMDK & Vtune™ Summit 8 pmemkv sample program -- nodejs

const kv = new KVEngine('vsmap', '{"path":"/dev/shm/"}');

kv.put('key1', 'value1'); assert(kv.count === 1);

assert(kv.get('key1') === 'value1');

kv.all((k) => console.log(` visited: ${k}`));

kv.remove('key1'); assert(!kv.exists('key1')); NOTE: kv.stop(); Maintained by Intel JSTC Binding based on NAPI Throw exception on error Buffer support coming soon!

SPDK, PMDK & Vtune™ Summit 9 pmemkv sample program -- RUBY

kv = KVEngine.new('vsmap', '{"path":"/dev/shm/"}')

kv.put('key1', 'value1') assert kv.count == 1

assert kv.get('key1').eql?('value1')

kv.all_strings {|k| puts " visited: #{k}"}

kv.remove('key1') assert !kv.exists('key1') NOTE: kv.stop Binding based on FFI Throw exception on error Supports string & byte array Iterator methods with type names

SPDK, PMDK & Vtune™ Summit 10 sources of latency Within HIGH-LEVEL BINDINGS

• # of round trips between high-level language & native code

• pmemkv language bindings (one round trip per operation) • Copy key/value data between persistent memory and high-level object • Create high-level object (string, byte[], reference type, callback/closure) • Depending on the type of high-level object… • Translate bytes to UTF-8 • String interning, reference counting or GC

• pmemkv core (native code) • Searching indexes in DRAM • Updating indexes in DRAM • Managing transactions • Allocating persistent memory

• Persistent Memory (read & write latencies)

SPDK, PMDK & Vtune™ Summit 11 relative performance of BINDINGS

NOTE: Single-threaded benchmarks on emulated persistent memory, 16 byte keys & values, C++ all/each pass pointers only, C++ & Java benchmarks use pre-generated keys, Ruby & NodeJS bindings use UTF-8 strings built during the benchmark

SPDK, PMDK & Vtune™ Summit 12 relative performance of BINDINGS

NOTE: Single-threaded benchmarks on emulated persistent memory, 16 byte keys & values, C++ all/each pass pointers only, C++ & Java benchmarks use pre-generated keys, Ruby & NodeJS bindings use UTF-8 strings built during the benchmark

SPDK, PMDK & Vtune™ Summit 13 storage engines

Implementations: Goals: cmap (PMDK concurrent map) Applications can use multiple engines vsmap (memkind) Engines are optimized for different workloads & capabilities (threading, vcmap (memkind) persistence, iterating, sorting) tree3 / stree (experimental) All engines work with all utilities and caching (experimental) language bindings Engines can use other engines Engines from the community

SPDK, PMDK & Vtune™ Summit 14 AVAILABLE ENGINES

SPDK, PMDK & Vtune™ Summit 15 contributing ENGINES is easy

https://github.com/pmem/pmemkv/blob/master/CONTRIBUTING.md#engines

SPDK, PMDK & Vtune™ Summit 16 pmemkv roadmap

1.0 Release: 1.1 Release: C/C++, Java, JavaScript, Ruby bindings Python bindings cmap, vmap, vcmap engines csmap, caching engines Automated tests & CI environment Third-party engines? pmemkv_bench (port of db_bench) Pool partitioning

Q2 2019 (estimated) Q4 2019 (estimated)

SPDK, PMDK & Vtune™ Summit 17 call to action

Star/watch us on GitHub! https://github.com/pmem/pmemkv

SPDK, PMDK & Vtune™ Summit 18