Skip to content

ppad-tech/lmdb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ppad-lmdb

Bindings to LMDB (Lightning Memory-Mapped Database), which is an embedded ACID key-value store.

This library exposes a minimal subset of the LMDB API, mainly supporting LMDB environments, transactions, basic row operations (get, put, del), and range scans.

Usage

A sample GHCi session:

  > :set -XOverloadedStrings
  > import qualified Database.LMDB as L
  >
  > -- envMapSize caps the on-disk size; the default (10 MiB) is
  > -- intentionally small. writes past it fail with LMDBMapFull,
  > -- so set it to something appropriate for your workload
  > let flags = L.defaultEnvFlags
  >       { L.envNoSubdir = True
  >       , L.envMapSize  = 256 * 1024 * 1024  -- 256 MiB
  >       }
  >
  > -- populate the env in a write transaction
  > L.withEnv "/tmp/mydb" flags $ \env ->
  >   L.withWriteTxn env $ \txn -> do
  >     dbi <- L.openDbi txn Nothing True
  >     L.put txn dbi "apple"  "red"
  >     L.put txn dbi "banana" "yellow"
  >     L.put txn dbi "cherry" "red"
  >
  > -- point lookup
  > L.withEnv "/tmp/mydb" flags $ \env ->
  >   L.withReadTxn env $ \txn -> do
  >     dbi <- L.openDbi txn Nothing False
  >     L.get txn dbi "banana"
  Just "yellow"
  >
  > -- range scan; every entry with key >= "b"
  > L.withEnv "/tmp/mydb" flags $ \env ->
  >   L.withReadTxn env $ \txn -> do
  >     dbi <- L.openDbi txn Nothing False
  >     L.withCursor txn dbi $ \cur -> do
  >       let go acc Nothing   = pure (reverse acc)
  >           go acc (Just kv) = L.cursorNext cur >>= go (kv : acc)
  >       L.cursorSeek cur "b" >>= go []
  [("banana","yellow"),("cherry","red")]

Performance

Current benchmark figures on an M4 Silicon MacBook Air look like (use cabal bench to run the benchmark suite):

  benchmarking put/1k inserts (one txn)
  time                 559.5 μs   (557.5 μs .. 562.0 μs)
                       1.000 R²   (0.999 R² .. 1.000 R²)
  mean                 561.8 μs   (559.6 μs .. 567.0 μs)
  std dev              11.34 μs   (5.445 μs .. 21.32 μs)

  benchmarking put/10k inserts (one txn)
  time                 4.026 ms   (4.016 ms .. 4.037 ms)
                       1.000 R²   (1.000 R² .. 1.000 R²)
  mean                 4.013 ms   (4.005 ms .. 4.022 ms)
  std dev              26.80 μs   (22.08 μs .. 36.75 μs)

  benchmarking get/1k random hits
  time                 307.1 μs   (306.3 μs .. 308.1 μs)
                       1.000 R²   (1.000 R² .. 1.000 R²)
  mean                 308.0 μs   (307.3 μs .. 309.4 μs)
  std dev              3.368 μs   (1.893 μs .. 5.357 μs)

  benchmarking get/10k random hits
  time                 2.882 ms   (2.872 ms .. 2.893 ms)
                       1.000 R²   (1.000 R² .. 1.000 R²)
  mean                 2.884 ms   (2.879 ms .. 2.889 ms)
  std dev              16.25 μs   (13.40 μs .. 21.54 μs)

  benchmarking cursor/scan 10k entries
  time                 1.249 ms   (1.245 ms .. 1.258 ms)
                       0.999 R²   (0.996 R² .. 1.000 R²)
  mean                 1.251 ms   (1.245 ms .. 1.281 ms)
  std dev              35.00 μs   (5.595 μs .. 82.99 μs)

Documentation

Haddocks (API documentation, etc.) are hosted at docs.ppad.tech/lmdb.

Development

You'll require Nix with flake support enabled. Enter a development shell with:

$ nix develop

Then do e.g.:

$ cabal repl ppad-lmdb

to get a REPL for the main library.

About

Minimal Haskell bindings to LMDB.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors