<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>lmdb, branch HEAD</title>
<subtitle>Minimal LMDB bindings for Haskell.
</subtitle>
<entry>
<id>fcc8fd9b88e6cc81d8a282143cbf09804b6e48c6</id>
<published>2026-05-24T20:50:15Z</published>
<updated>2026-05-24T20:50:15Z</updated>
<title type="text">release: v0.1.0</title>
<link rel="alternate" type="text/html" href="commit/fcc8fd9b88e6cc81d8a282143cbf09804b6e48c6.html" />
<author>
<name>Jared Tobin</name>
<email>jared@jtobin.io</email>
</author>
<content type="text">commit fcc8fd9b88e6cc81d8a282143cbf09804b6e48c6
parent c8d31da1834ea29bc4e00a6cdfc748fc3ebd01b1
Author: Jared Tobin &lt;jared@jtobin.io&gt;
Date:   Sun, 24 May 2026 18:20:15 -0230

release: v0.1.0

</content>
</entry>
<entry>
<id>c8d31da1834ea29bc4e00a6cdfc748fc3ebd01b1</id>
<published>2026-05-24T20:40:38Z</published>
<updated>2026-05-24T20:48:12Z</updated>
<title type="text">docs: flesh out README sample, add Performance section</title>
<link rel="alternate" type="text/html" href="commit/c8d31da1834ea29bc4e00a6cdfc748fc3ebd01b1.html" />
<author>
<name>Jared Tobin</name>
<email>jared@jtobin.io</email>
</author>
<content type="text">commit c8d31da1834ea29bc4e00a6cdfc748fc3ebd01b1
parent 08059713a94e7dffca071f84a936ee7124a77c27
Author: Jared Tobin &lt;jared@jtobin.io&gt;
Date:   Sun, 24 May 2026 18:10:38 -0230

docs: flesh out README sample, add Performance section

The previous GHCi sample only covered put/get. Expand it to:

- highlight envMapSize as the first thing users should think
  about (the 10 MiB default is the most common footgun)
- demonstrate a cursor range scan via cursorSeek + cursorNext

</content>
</entry>
<entry>
<id>08059713a94e7dffca071f84a936ee7124a77c27</id>
<published>2026-05-24T19:52:40Z</published>
<updated>2026-05-24T19:52:40Z</updated>
<title type="text">silence CApiFFI pointer-type warnings on clang 15+</title>
<link rel="alternate" type="text/html" href="commit/08059713a94e7dffca071f84a936ee7124a77c27.html" />
<author>
<name>Jared Tobin</name>
<email>jared@jtobin.io</email>
</author>
<content type="text">commit 08059713a94e7dffca071f84a936ee7124a77c27
parent abfe775537fe006c4bac13092c007844d209ab92
Author: Jared Tobin &lt;jared@jtobin.io&gt;
Date:   Sun, 24 May 2026 17:22:40 -0230

silence CApiFFI pointer-type warnings on clang 15+

For each `foreign import capi` declaration over an opaque
struct (`Ptr (Ptr MDB_env)` etc.), GHC emits a tiny wrapper:

  HsInt32 ghczuwrapper...(void** a1) { return mdb_env_create(a1); }

clang 15+ flags the `void**` -&gt; `MDB_env**` conversion under
-Wincompatible-pointer-types, and GHC prints those warnings
wrapped in its own diagnostic format (&quot;error: warning: ...&quot;).
The build still succeeds, but the output is noisy and reads as
if it&#39;s failing.

Add `-optc-Wno-incompatible-pointer-types` so the warning is
suppressed for the wrapper compilation. Doesn&#39;t touch our own
C (already silenced via `cc-options: -w`) or our Haskell.

</content>
</entry>
<entry>
<id>abfe775537fe006c4bac13092c007844d209ab92</id>
<published>2026-05-24T19:49:17Z</published>
<updated>2026-05-24T19:49:17Z</updated>
<title type="text">vendor LMDB 0.9.33 under cbits/</title>
<link rel="alternate" type="text/html" href="commit/abfe775537fe006c4bac13092c007844d209ab92.html" />
<author>
<name>Jared Tobin</name>
<email>jared@jtobin.io</email>
</author>
<content type="text">commit abfe775537fe006c4bac13092c007844d209ab92
parent d2eb60d378143cf6612eeda250acce2c6471f69a
Author: Jared Tobin &lt;jared@jtobin.io&gt;
Date:   Sun, 24 May 2026 17:19:17 -0230

vendor LMDB 0.9.33 under cbits/

Drop the system-liblmdb dependency in favour of vendoring the
upstream LMDB C sources. Five files from the LMDB_0.9.33 tag of
LMDB/lmdb on GitHub: lmdb.h, mdb.c, midl.c, midl.h, and LICENSE
(the OpenLDAP Public License 2.8, MIT-compatible).

Motivation: this lets `cabal install ppad-lmdb` succeed on any
host with a C toolchain, without needing distro packages, nix,
pkg-config, or matching liblmdb header versions. LMDB is tiny
(~10k LOC, two .c files, C89, depends only on POSIX/Win32), so
the cost of vendoring is low.

Changes:

- cbits/: lmdb.h, mdb.c, midl.c, midl.h, LICENSE.
- ppad-lmdb.cabal: drop `pkgconfig-depends: lmdb`; add
  `c-sources` + `include-dirs: cbits` + `cc-options: -w` (LMDB
  compiles with some old-style warnings that aren&#39;t our
  problem); add `extra-libraries: pthread` everywhere except
  Windows; list the vendored files under `extra-source-files`
  so `sdist` ships them. Synopsis/description updated.
- flake.nix: drop `pkgs.lmdb` and `pkgs.pkg-config` from
  buildInputs; banner now reports the vendored revision instead
  of the nixpkgs version.
- README + Database.LMDB haddock: replace the pkg-config text
  with the vendoring note (the haddock was already implicitly
  claiming this).

Verification: clean rebuild succeeds; all 8 tests pass; bench
numbers within noise of the pre-vendoring run (put 1k 572 us
vs 590 us, get 1k 307 us vs 313 us, scan 10k 1.21 ms vs
1.22 ms). The GHC CApiFFI `void** -&gt; MDB_env**` warnings are
unchanged from before -- they come from GHC&#39;s generated
wrappers, not the vendored code.

</content>
</entry>
<entry>
<id>d2eb60d378143cf6612eeda250acce2c6471f69a</id>
<published>2026-05-24T19:17:15Z</published>
<updated>2026-05-24T19:17:15Z</updated>
<title type="text">flake: formatting nit</title>
<link rel="alternate" type="text/html" href="commit/d2eb60d378143cf6612eeda250acce2c6471f69a.html" />
<author>
<name>Jared Tobin</name>
<email>jared@jtobin.io</email>
</author>
<content type="text">commit d2eb60d378143cf6612eeda250acce2c6471f69a
parent d53d51b03e1160de9e3105cdbfd5b482e5025dbd
Author: Jared Tobin &lt;jared@jtobin.io&gt;
Date:   Sun, 24 May 2026 16:47:15 -0230

flake: formatting nit

</content>
</entry>
<entry>
<id>d53d51b03e1160de9e3105cdbfd5b482e5025dbd</id>
<published>2026-05-24T19:05:26Z</published>
<updated>2026-05-24T19:05:26Z</updated>
<title type="text">perf: inline hot paths and combine MDB_val allocations</title>
<link rel="alternate" type="text/html" href="commit/d53d51b03e1160de9e3105cdbfd5b482e5025dbd.html" />
<author>
<name>Jared Tobin</name>
<email>jared@jtobin.io</email>
</author>
<content type="text">commit d53d51b03e1160de9e3105cdbfd5b482e5025dbd
parent 0c973be28ac9a83e02ec64cf7811aeee03b3e7aa
Author: Jared Tobin &lt;jared@jtobin.io&gt;
Date:   Sun, 24 May 2026 16:35:26 -0230

perf: inline hot paths and combine MDB_val allocations

The Haskell layer over the FFI was using `with` + `alloca` pairs and
shared `cursorAt` with a `Maybe BS.ByteString` dispatch on every cursor
step. None of it costs much per call, but cursor scans iterate it tens
of thousands of times per second.

- INLINE on `check`, `withBSAsVal`, `peekVal`, `get`, `put`, `del`,
  all `cursor*` wrappers, and the `MDB_val` Storable methods. Lets
  `-O1` consumers see through the wrappers at each call site.
- `withBSAsVal` / `peekVal` poke fields directly via `pokeByteOff`
  / `peekByteOff` rather than going through `with` and the Storable
  instance. Same generated code under inlining, but no longer depends
  on it.
- `get`, `put`, `cursorMove`, `cursorSeek` use a single
  `allocaBytes 32` to hold both the input-key and output-value (or
  the two input) `MDB_val` structs side-by-side instead of two
  separate allocations.
- `cursorAt` split into `cursorMove` (no input key — used by
  first/last/next/prev) and an inlined seek body. Removes the
  per-call `Maybe` dispatch that the hot scan path was paying.

Criterion (3s time-limit):
  put 10k inserts   4.319 ms  -&gt;  4.160 ms   (-3.7%)
  get 1k random     332.1 us  -&gt;  312.8 us   (-5.8%)
  get 10k random    3.200 ms  -&gt;  2.971 ms   (-7.2%)
  cursor scan 10k   1.439 ms  -&gt;  1.217 ms   (-15.4%)

Weigh:
  1k put            9,919,040 B  -&gt;  9,782,608 B   (-1.4%)
  1k get            5,063,024 B  -&gt;  4,922,792 B   (-2.8%)
  scan 1k entries     423,448 B  -&gt;    267,040 B   (-37%)

Test suite still passes.

Also bundles unrelated doc tidy-ups: README badges, dev section
pointing at `nix develop`, cabal synopsis/description reflow.

</content>
</entry>
<entry>
<id>0c973be28ac9a83e02ec64cf7811aeee03b3e7aa</id>
<published>2026-05-24T18:47:57Z</published>
<updated>2026-05-24T18:47:57Z</updated>
<title type="text">init: minimal LMDB bindings</title>
<link rel="alternate" type="text/html" href="commit/0c973be28ac9a83e02ec64cf7811aeee03b3e7aa.html" />
<author>
<name>Jared Tobin</name>
<email>jared@jtobin.io</email>
</author>
<content type="text">commit 0c973be28ac9a83e02ec64cf7811aeee03b3e7aa
Author: Jared Tobin &lt;jared@jtobin.io&gt;
Date:   Sun, 24 May 2026 16:17:57 -0230

init: minimal LMDB bindings

A first cut at ppad-lmdb. Wraps the system liblmdb (via
pkg-config, provided by pkgs.lmdb in the flake) and exposes a
safe, bracketed interface keyed on strict ByteStrings.

Surface (Database.LMDB):
- Env / open / close / withEnv with an EnvFlags record
- Phantom-typed transactions: withReadTxn (Txn RO) and
  withWriteTxn (Txn RW). Writing through an RO Txn fails to
  type-check
- openDbi, get / put / del
- Cursors: withCursor, cursorFirst / Last / Next / Prev,
  cursorSeek (MDB_SET_RANGE)
- LMDBException with the common cases tagged plus a catch-all

Database.LMDB.Internal exposes the raw foreign-import-capi
declarations and flag constants for power users.

Tests (tasty): six unit cases (roundtrip, missing key, del
truthiness, write-txn rollback on exception, cursor walk,
cursorSeek) plus two QuickCheck properties (put/get roundtrip,
cursor enumerates Map.toAscList).

Benches: criterion bench/Main.hs covers put/get/cursor at 1k/10k
entries; weigh bench/Weight.hs reports per-op allocations.

Note: sanitize flag intentionally omitted - we vendor no C, so
clang doesn&#39;t add the ASan runtime to the link line and the flag
would only give a false signal of safety.

</content>
</entry>
</feed>
