Skip to content

Commit ae9baaf

Browse files
committed
Merge branch 'release/0.3.4'
2 parents 4a9b01a + 111da75 commit ae9baaf

7 files changed

Lines changed: 130 additions & 105 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# CHANGELOG
2+
# 0.3.4
3+
* Makes io-uring an option disabled by default (AWS ECS crashes)
4+
* Reverts harcoded values in Cozo/cozorocks that where left during mem leak fix and allow them to be passed as ENV VARS. `option` is the main way to set those values, ENV VARS will override them
5+
26
# 0.3.3
37

48
## Bug Fixes
@@ -69,7 +73,7 @@
6973
* Added `COZODB_BACKEND` environment variable support in Makefile
7074
- `make build` or `make build-rocksdb` - Build with cozorocks (default)
7175
- `COZODB_BACKEND=newrocksdb make build` or `make build-newrocksdb` - Build with rust-rocksdb
72-
* Note: `rebar3_cargo` does not support passing Cargo features; use Makefile targets
76+
* Build options work with `make`, `rebar3 compile`, and `mix compile` via env vars
7377

7478
## Improvements
7579
* Improved Erlang serialization for better performance

Makefile

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,33 @@ export JEMALLOC_SYS_WITH_MALLOC_CONF ?= background_thread:false,dirty_decay_ms:1
1919
# IMPORTANT: The two backends are MUTUALLY EXCLUSIVE due to allocator conflicts.
2020
COZODB_BACKEND ?= rocksdb
2121

22-
# Cargo feature flags based on selected backend
22+
# io_uring for RocksDB async I/O (Linux-only, requires liburing-dev):
23+
# COZODB_IO_URING=true - Enable io_uring (bare-metal Linux recommended)
24+
# COZODB_IO_URING=false - Disable io_uring (default, safe for containers)
25+
# WARNING: io_uring + jemalloc + RocksDB 10.9.1 crashes in container environments
26+
# (Docker named volumes, AWS ECS) due to TLS conflicts with the BEAM VM.
27+
COZODB_IO_URING ?= false
28+
29+
# Cargo feature flags based on selected backend and options
30+
EXTRA_CARGO_FEATURES :=
31+
32+
ifeq ($(COZODB_IO_URING),true)
33+
EXTRA_CARGO_FEATURES += io-uring
34+
endif
35+
2336
ifeq ($(COZODB_BACKEND),newrocksdb)
37+
ifneq ($(EXTRA_CARGO_FEATURES),)
38+
CARGO_FEATURES := --no-default-features --features "new-rocksdb-default,$(EXTRA_CARGO_FEATURES)"
39+
else
2440
CARGO_FEATURES := --no-default-features --features "new-rocksdb-default"
41+
endif
42+
else
43+
ifneq ($(EXTRA_CARGO_FEATURES),)
44+
CARGO_FEATURES := --features "$(EXTRA_CARGO_FEATURES)"
2545
else
2646
CARGO_FEATURES :=
2747
endif
48+
endif
2849

2950
.PHONY: all
3051
all: build
@@ -36,7 +57,7 @@ build: cargo-build
3657
# Build with the selected backend (controlled by COZODB_BACKEND env var)
3758
.PHONY: cargo-build
3859
cargo-build:
39-
@echo "Building with COZODB_BACKEND=$(COZODB_BACKEND)"
60+
@echo "Building with COZODB_BACKEND=$(COZODB_BACKEND) COZODB_IO_URING=$(COZODB_IO_URING)"
4061
cd native/cozodb && cargo build --release $(CARGO_FEATURES)
4162
@mkdir -p priv/crates/cozodb
4263
@cp native/cozodb/target/release/libcozodb.so priv/crates/cozodb/cozodb.so 2>/dev/null || \

README.md

Lines changed: 66 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ CozoDB is a FOSS embeddable, transactional, relational-graph-vector database, wi
1313
- [RocksDB Backends](#rocksdb-backends)
1414
- [rocksdb (cozorocks)](#1-rocksdb-cozorocks---default)
1515
- [newrocksdb (rust-rocksdb)](#2-newrocksdb-rust-rocksdb---alternative)
16+
- [Build Options](#build-options)
17+
- [io_uring](#io_uring)
1618
- [Configuration](#configuration)
1719
- [jemalloc](#jemalloc)
1820
- [Docker](#docker)
@@ -30,8 +32,8 @@ CozoDB is a FOSS embeddable, transactional, relational-graph-vector database, wi
3032
{ok, Result} = cozodb:run(Db, "?[] <- [[1, 2, 3]]").
3133

3234
%% Close the database
33-
%% Notice that close no longer releases the NIF resource. This will be done
34-
%% when the Erlang GC triggers as long as you no longer have a reference to
35+
%% Notice that close no longer releases the NIF resource. This will be done
36+
%% when the Erlang GC triggers as long as you no longer have a reference to
3537
%% `Db`.
3638
ok = cozodb:close(Db).
3739
```
@@ -42,10 +44,11 @@ ok = cozodb:close(Db).
4244

4345
| Platform | Dependencies |
4446
|----------|--------------|
45-
| **Runtime** | Erlang OTP26+ and/or Elixir (latest) |
46-
| **Build** | Rust 1.76.0+ |
47+
| **Runtime** | Erlang OTP27+ and/or Elixir (latest) |
48+
| **Build** | Rust 1.76.0+, Make |
4749
| **macOS** | `liblz4`, `libssl` |
48-
| **Linux** | `build-essential`, `liblz4-dev`, `libncurses-dev`, `libsnappy-dev`, `libssl-dev`, `liburing-dev`, `liburing2`, `pkg-config` |
50+
| **Linux** | `build-essential`, `liblz4-dev`, `libncurses-dev`, `libsnappy-dev`, `libssl-dev`, `pkg-config` |
51+
| **Linux (io_uring)** | All of the above plus `liburing-dev` (see [io_uring](#io_uring)) |
4952

5053
### Erlang
5154

@@ -119,13 +122,7 @@ An alternative RocksDB backend using the official **rust-rocksdb** crate. This b
119122
120123
#### Building with newrocksdb
121124

122-
To use the `newrocksdb` backend, you must build with the `new-rocksdb-default` feature instead of the default features.
123-
124-
> **Note:** The `rebar3_cargo` plugin does not support passing Cargo feature flags. Use the Makefile targets or manual Cargo build as described below.
125-
126-
##### Option 1: Makefile with Environment Variable (Recommended)
127-
128-
Use the provided Makefile with the `COZODB_BACKEND` environment variable:
125+
To use the `newrocksdb` backend, set the `COZODB_BACKEND` environment variable at compile time:
129126

130127
```bash
131128
# Use newrocksdb backend
@@ -140,40 +137,12 @@ make build
140137
make build-rocksdb
141138
```
142139

143-
##### Option 2: Manual Cargo Build
144-
145-
Build the NIF manually before running rebar3:
140+
This works the same way when `cozodb` is used as a rebar3/mix dependency:
146141

147142
```bash
148-
# In native/cozodb directory
149-
cargo build --release --no-default-features --features "new-rocksdb-default"
150-
151-
# Copy the built library to priv/
152-
mkdir -p ../../priv/crates/cozodb
153-
cp target/release/libcozodb.dylib ../../priv/crates/cozodb/cozodb.so # macOS
154-
# or: cp target/release/libcozodb.so ../../priv/crates/cozodb/cozodb.so # Linux
155-
156-
# Then compile Erlang code only
157-
cd ../..
158-
rebar3 compile
143+
COZODB_BACKEND=newrocksdb rebar3 compile
159144
```
160145

161-
##### Option 3: Modify Cargo.toml
162-
163-
Edit `native/cozodb/Cargo.toml` to change the default features permanently:
164-
165-
```toml
166-
[features]
167-
default = [
168-
"cozo/storage-sqlite",
169-
"cozo/storage-new-rocksdb", # Changed from storage-rocksdb
170-
"cozo/graph-algo",
171-
"jemalloc"
172-
]
173-
```
174-
175-
Then build normally with `make build` or `rebar3 compile`.
176-
177146
#### newrocksdb Environment Variables
178147

179148
The `newrocksdb` backend reads configuration from `COZO_ROCKSDB_*` environment variables:
@@ -263,6 +232,36 @@ os:putenv("COZO_ROCKSDB_ENABLE_STATISTICS", "true"),
263232
{ok, Db} = cozodb:open(newrocksdb, "/path/to/db").
264233
```
265234

235+
## Build Options
236+
237+
All build options are controlled via environment variables and work with `make build`, `rebar3 compile`, and `mix compile`:
238+
239+
| Variable | Values | Default | Description |
240+
|----------|--------|---------|-------------|
241+
| `COZODB_BACKEND` | `rocksdb`, `newrocksdb` | `rocksdb` | RocksDB backend selection |
242+
| `COZODB_IO_URING` | `true`, `false` | `false` | Enable Linux io_uring async I/O |
243+
244+
### io_uring
245+
246+
Linux io_uring support for RocksDB async I/O is available as an opt-in build feature. It is **disabled by default** because the combination of io_uring + jemalloc + RocksDB 10.9.1 causes segfaults in container environments (Docker with named volumes, AWS ECS). This is due to TLS (Thread Local Storage) conflicts between RocksDB's per-thread io_uring instances, jemalloc's thread caches, and the BEAM VM's dirty IO scheduler threads.
247+
248+
When disabled, RocksDB uses standard `pread`/`pwrite` syscalls which perform well across all environments.
249+
250+
To enable io_uring (Linux-only, requires `liburing-dev`):
251+
252+
```bash
253+
# Direct build
254+
COZODB_IO_URING=true make build
255+
256+
# As a rebar3 dep
257+
COZODB_IO_URING=true rebar3 compile
258+
259+
# Docker
260+
docker build --build-arg COZODB_IO_URING=true -t myapp .
261+
```
262+
263+
> **WARNING:** Only enable io_uring for bare-metal Linux deployments where you have verified it works with your kernel version. Do not enable in container environments (Docker, ECS, Kubernetes).
264+
266265
## Configuration
267266

268267
### jemalloc
@@ -320,6 +319,14 @@ For container compatibility, set `JEMALLOC_SYS_WITH_MALLOC_CONF` to bake safe de
320319
ENV JEMALLOC_SYS_WITH_MALLOC_CONF="background_thread:false,dirty_decay_ms:1000,muzzy_decay_ms:1000"
321320
```
322321

322+
#### io_uring in Docker
323+
324+
io_uring is disabled by default, which is the recommended setting for container deployments. If you need to enable it (not recommended), pass the build arg:
325+
326+
```bash
327+
docker build --build-arg COZODB_IO_URING=true -t myapp .
328+
```
329+
323330
### Memory Tuning Tips
324331

325332
| Use Case | Recommendation |
@@ -330,39 +337,33 @@ ENV JEMALLOC_SYS_WITH_MALLOC_CONF="background_thread:false,dirty_decay_ms:1000,m
330337

331338
## Development
332339

333-
### Upgrading the cozo Dependency
340+
### Building
334341

335342
```bash
336-
cd native/cozodb
337-
cargo update -p cozo
338-
```
339-
340-
### Using newrocksdb Backend as a Consumer
341-
342-
By default, cozodb compiles with the `rocksdb` (cozorocks) backend. If you need the `newrocksdb` backend with environment variable configuration in your own project, you have two options:
343+
# Default build (rocksdb backend, no io_uring)
344+
make build
343345

344-
#### Option A: Fork and Modify (Recommended)
346+
# With newrocksdb backend
347+
COZODB_BACKEND=newrocksdb make build
345348

346-
1. Fork the cozodb repository
347-
2. Modify `native/cozodb/Cargo.toml` to use `new-rocksdb-default` as the default features
348-
3. Point your dependency to your fork
349+
# With io_uring (Linux bare-metal only)
350+
COZODB_IO_URING=true make build
349351

350-
#### Option B: Pre-build the NIF
352+
# Combine options
353+
COZODB_BACKEND=newrocksdb COZODB_IO_URING=true make build
354+
```
351355

352-
Before running `rebar3 compile` in your project:
356+
### Running Tests
353357

354358
```bash
355-
# Clone cozodb
356-
git clone https://github.com/leapsight/cozodb.git /tmp/cozodb
357-
cd /tmp/cozodb
359+
make test
360+
```
358361

359-
# Build with newrocksdb backend
360-
COZODB_BACKEND=newrocksdb make cargo-build
362+
### Upgrading the cozo Dependency
361363

362-
# Copy the built NIF to your project's _build directory
363-
# (after rebar3 has fetched dependencies)
364-
mkdir -p YOUR_PROJECT/_build/default/lib/cozodb/priv/crates/cozodb
365-
cp priv/crates/cozodb/cozodb.so YOUR_PROJECT/_build/default/lib/cozodb/priv/crates/cozodb/
364+
```bash
365+
cd native/cozodb
366+
cargo update -p cozo
366367
```
367368

368369
## License

benchmark/Dockerfile

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
FROM elixir:1.18-otp-27
55

6+
# Build args for compile-time feature selection
7+
# Set COZODB_IO_URING=true to enable io_uring (not recommended for containers)
8+
ARG COZODB_IO_URING=false
9+
610
# Install build dependencies
711
RUN apt-get update && apt-get install -y \
812
build-essential \
@@ -12,10 +16,14 @@ RUN apt-get update && apt-get install -y \
1216
clang \
1317
libclang-dev \
1418
pkg-config \
15-
liburing-dev \
1619
procps \
1720
&& rm -rf /var/lib/apt/lists/*
1821

22+
# Conditionally install liburing-dev when io_uring is enabled
23+
RUN if [ "$COZODB_IO_URING" = "true" ]; then \
24+
apt-get update && apt-get install -y liburing-dev && rm -rf /var/lib/apt/lists/*; \
25+
fi
26+
1927
# Install Rust
2028
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
2129
ENV PATH="/root/.cargo/bin:${PATH}"
@@ -39,8 +47,7 @@ ENV JEMALLOC_SYS_WITH_MALLOC_CONF="background_thread:false,dirty_decay_ms:1000,m
3947
# Different from macOS Apple Silicon which uses 16KB (LG_PAGE=14) or 64KB pages
4048
ENV JEMALLOC_SYS_WITH_LG_PAGE=12
4149

42-
43-
RUN cd native/cozodb && cargo build --release
50+
RUN COZODB_IO_URING=${COZODB_IO_URING} make cargo-build
4451

4552
# Copy the built NIF to priv directory
4653
RUN mkdir -p priv/crates/cozodb && \

native/cozodb/Cargo.toml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "erlang-cozodb"
33
description = "Erlang NIF wrapper for CozoDB using Rustler."
44
authors = ["Alejandro M. Ramallo"]
5-
version = "0.3.3"
5+
version = "0.3.4"
66
edition = "2021"
77

88
[lib]
@@ -13,7 +13,7 @@ crate-type = ["cdylib"]
1313
[dependencies]
1414
rustler = {version = "=0.37.0", features = ["nif_version_2_17"]}
1515
# Using local path temporarily to test new memory stats functionality
16-
cozo = {git = "https://github.com/aramallo/cozo.git", tag = "v0.8.2-leapsight" }
16+
cozo = {git = "https://github.com/aramallo/cozo.git", tag = "v0.8.3-leapsight" }
1717
uuid = "1.3.3"
1818
threadpool = "1.8.1"
1919
once_cell = "1.21.3"
@@ -105,6 +105,13 @@ nif_alloc_rocksdb_jemalloc = ["nif_alloc", "tikv-jemalloc-ctl", "tikv-jemalloc-s
105105
# Requires: MALLOC_CONF="prof:true" at runtime to activate.
106106
jemalloc-profiling = ["tikv-jemallocator/profiling", "tikv-jemalloc-ctl/profiling", "tikv-jemalloc-sys/profiling"]
107107

108-
[target.'cfg(target_os = "linux")'.dependencies]
109-
cozo = { git = "https://github.com/aramallo/cozo.git", tag = "v0.8.2-leapsight", features = ["io-uring"] }
108+
# Enable Linux io_uring for RocksDB async I/O (Linux-only, requires liburing-dev).
109+
# Disabled by default due to crashes when combined with jemalloc on RocksDB 10.9.1
110+
# in container environments (Docker named volumes, AWS ECS).
111+
# The issue is a three-way interaction between RocksDB 10.9.1's per-thread
112+
# io_uring instances (ThreadLocalPtr/pthread TLS), jemalloc's TLS-based thread
113+
# caches, and the BEAM VM's many dirty IO scheduler threads.
114+
# RocksDB falls back to standard pread/pwrite which performs well.
115+
# Enable via: COZODB_IO_URING=true make build
116+
io-uring = ["cozo/io-uring"]
110117

0 commit comments

Comments
 (0)