Skip to main content

Memory-mapped columnar binary format for fast random-access I/O on structured arrays.

Project description

ColStore

A memory-mapped columnar binary format for fast, memory-efficient I/O on structured arrays. colstore lets you write a tabular dataset to a single .cstore file (in one shot or streamed across many records) and then load arbitrary row/column subsets without materializing the rest. Internally, columns are stored back-to-back as raw NumPy bytes, reads use np.memmap, and fancy-index gathers run through a parallel C++ kernel (OpenMP + software prefetching) bound via Cython. Process memory stays bounded by the size of the output you ask for; the source file is never fully read into RAM.

Install

pip install colstore

Building from source needs a C++17 compiler and CMake ≥ 3.18. On macOS install libomp (brew install libomp) to get the parallel kernel; without it the build still succeeds but the kernel runs single-threaded.

Quick start

import colstore

# One-shot write + open. `.cstore` is the canonical extension.
ds = colstore.store(df, "data.cstore")

# Or open an existing file for read.
ds = colstore.open("data.cstore")

# Indexing returns lazy views; no data is read yet.
ds['price']                          # ColumnView
ds[100:200]                          # TableView
ds[100:200, 'price']                 # ColumnView
ds[100:200, ['price', 'qty']]        # TableView
ds[[1, 5, 9], ['price', 'qty']]      # TableView (fancy rows + cols)

# Materialize through one of the materialization methods.
ds['price'].array()                          # 1D ndarray
ds[indices, ['price', 'qty']].dict()         # dict of 1D arrays
ds[indices, ['price', 'qty']].recarray()     # structured ndarray
ds[indices, ['price', 'qty']].frame()        # pandas DataFrame

Writing

colstore.store(data, path) is the one-shot path; it dispatches on the input type:

import colstore
import numpy as np

# From a dict of 1D arrays.
colstore.store(
    {"x": np.arange(100, dtype=np.float32), "y": np.arange(100, dtype=np.int64)},
    "data.cstore",
)

# From a structured (record) array.
records = np.empty(100, dtype=[("price", np.float32), ("qty", np.int32)])
colstore.store(records, "data.cstore", mode="recreate")

# From a pandas DataFrame.
colstore.store(df, "data.cstore", mode="recreate")

mode="create" (default) refuses to overwrite; mode="recreate" truncates an existing file.

For multi-record streaming writes (data arriving in batches, or appending to an existing file), use colstore.create / colstore.recreate / colstore.update:

# Append-only stream into a new file.
with colstore.create("data.cstore") as f:
    for batch in source:
        f.write({"x": batch.x, "y": batch.y})

# Resume appending to an existing file. Schema is loaded from the manifest
# and every write must match it. Bytes from a crashed prior writer are
# truncated on open.
with colstore.update("data.cstore") as f:
    f.write({"x": more_x, "y": more_y})

The writer commits records atomically on close() by rewriting a 32-byte counters block. A reader opening the file mid-write sees only what the last successful close committed.

The streaming writers (create / recreate / update) and compact take an advisory flock for the duration of the write, so a second writer on the same file fails fast with a clear error instead of corrupting it. On filesystems that don't implement flock (some Lustre, GPFS, and NFS mounts), the lock is skipped with a one-time warning and the write proceeds — there is no lock to contend for on such a mount, so concurrent-writer detection is simply unavailable there.

Compaction

A streaming write produces one record per write() call. Reads of slice and sorted-fancy index patterns scale near-flat with record count, but unsorted-fancy reads degrade as records accumulate. colstore.compact collapses all records into one, so every read pattern takes the single-record fast path:

colstore.compact("data.cstore")                 # in-place
colstore.compact("data.cstore", out="new.cstore")  # leave source untouched

In-place compaction writes to a sibling temp file and atomically renames into place; the source is untouched on failure. The byte copy uses os.sendfile on Linux (kernel-space copy, no Python-side surfacing) and shutil.copyfileobj on macOS/Windows; on both paths memory footprint is bounded by the kernel/I/O buffer (tens of KB) regardless of file size — files much larger than RAM compact fine.

Introspection

i = colstore.info("data.cstore")
# ColStoreInfo(path='data.cstore', n_rows=1_000_000, n_records=42,
#              columns=[a:<f4, b:<i8], file_size=8_001_232B,
#              needs_compaction=True)

colstore.schema("data.cstore")
# [{'name': 'a', 'dtype': '<f4', 'encoding': 'raw', 'nullable': False}, ...]

Both info and schema read only the file header (no record bodies are scanned), so they're cheap on multi-GB files.

Configuration

from colstore import (
    set_max_workers,
    set_default_madvise,
    set_default_backend,
    set_gather_thread_cap,
    calibrate,
)
from colstore import config

set_max_workers(8)                 # parallel gathers across columns
set_default_madvise("sequential")  # OS read-ahead hint for sorted-index reads
set_default_backend("cpp")         # gather kernel: cpp | numpy | numba
set_gather_thread_cap(16)          # threads per gather (default scales with socket count)
config.set_numa_policy("auto")     # page placement: auto (interleave on multi-node) | local
calibrate()                        # one-time: measure the thread/prefetch knees for this host

How reads parallelize

A gather's thread count is decided in two stages. A single-column read runs at the full gather thread cap; a multi-column read (dict / recarray / frame) either splits the cap across a per-column pool or runs the columns sequentially at the full cap, depending on the route taken. Either way the kernel's resolve_thread_count has the final say: it scales the actual thread count with the number of indices and clamps it to the cap, so small reads stay serial and only large ones spend the whole budget.

Gather thread decision flow

The cap itself defaults to half the physical cores, bounded by a per-socket allowance so multi-socket hosts (with more memory channels) get a higher default; colstore.autotune refines it per host by measuring the saturation knee directly.

NUMA placement

On a multi-node (multi-socket) Linux host, the default auto policy interleaves a store's pages across nodes so the memory controllers share the load; on a single-node host, or under local, it leaves the kernel's first-touch placement that keeps pages near the reading thread. Placement is decided at the first page fault, so warm pages cannot be moved — only a cold read (pages not yet resident) is placed according to the policy.

NUMA placement decision

Whether the best cold-read placement depends on the access pattern was the one case the warm sweep never covered. benchmark/check_cold_read_placement.py measured it on a multi-node host: cold, across contiguous, sorted-fancy, and random-scatter selectors, interleave was at least as fast as local for every pattern (1.10× on the contiguous scan, within noise otherwise) and never slower. The winner never flips to local, so there is nothing for a per-pattern mechanism to exploit and the single auto default stands. Revisit only if a host or access pattern is found where local beats interleave for cold reads.

Pinning the gather threads (rather than placing pages) is a separate, opt-in lever that ships off: a placement × binding × cap sweep measured spread binding 24–51% slower on a multi-node host, so gather_binding defaults to off and the realized path is the unbound default pool.

Gather thread binding status

On-disk format

The .cstore on-disk format

[magic 8B = b"CSTORE\x00\x01"]
[counters 32B: n_records(8) + committed_rows(8) + crc32(4) + reserved(12)]
[manifest_len 8B (u64 little-endian)]
[manifest_json: format_version + columns + manifest_crc32]
[zero-padding to 64-byte alignment]
[record_0 header 32B][record_0 body, padded to 8B]
[record_1 header 32B][record_1 body, padded to 8B]
...

The JSON manifest is immutable and carries only the schema; the mutable record/row counters live in their own fixed-position 32-byte block (with its own CRC) right after the magic. Each record body holds the columns back-to-back as raw bytes. A one-shot write produces a single-record file that reads via a per-column memmap fast path; a streamed write produces a multi-record file with per-pattern dispatch (contiguous range, sorted fancy, unsorted fancy).

Single-record vs multi-record column layout

Supported dtypes

All fixed-size NumPy dtypes are supported: float32/float64, int8/16/32/64, uint8/16/32/64, bool, datetime64, timedelta64, and fixed-width strings (S bytes and U unicode, with the width baked into the dtype, e.g. S16 or U8). Object dtype (variable-length strings, Python objects) is rejected at write time — the design point is zero-copy random access, which requires a fixed stride per row.

Documentation

In-depth guides live in docs/:

  • Performance & internals — the file layout, the kernel behind each access pattern, how reads parallelize, NUMA placement, and zero-copy.
  • Gather diagnostics — re-measure the thread, binding, and placement knobs on your own hardware.
  • Optimization series — the cumulative record of every optimization and the measurement behind it.
  • Valgrind leak checking — the native-leak Memcheck harness under scripts/.

The docs index lists everything, including the diagrams.

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

colstore-0.3.1.tar.gz (324.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

colstore-0.3.1-cp313-cp313-win_amd64.whl (187.0 kB view details)

Uploaded CPython 3.13Windows x86-64

colstore-0.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (303.8 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

colstore-0.3.1-cp313-cp313-macosx_11_0_arm64.whl (189.4 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

colstore-0.3.1-cp312-cp312-win_amd64.whl (187.3 kB view details)

Uploaded CPython 3.12Windows x86-64

colstore-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (306.2 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

colstore-0.3.1-cp312-cp312-macosx_11_0_arm64.whl (189.7 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

colstore-0.3.1-cp311-cp311-win_amd64.whl (187.7 kB view details)

Uploaded CPython 3.11Windows x86-64

colstore-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (305.9 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

colstore-0.3.1-cp311-cp311-macosx_11_0_arm64.whl (186.4 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

colstore-0.3.1-cp310-cp310-win_amd64.whl (187.7 kB view details)

Uploaded CPython 3.10Windows x86-64

colstore-0.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (305.5 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

colstore-0.3.1-cp310-cp310-macosx_11_0_arm64.whl (186.9 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file colstore-0.3.1.tar.gz.

File metadata

  • Download URL: colstore-0.3.1.tar.gz
  • Upload date:
  • Size: 324.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for colstore-0.3.1.tar.gz
Algorithm Hash digest
SHA256 8a68e658084cb5322f1cba933b32427c376da1ff74565ad8b7fcd3ef0ae350e8
MD5 8617849a3fc8eccfd333bc23aa76850e
BLAKE2b-256 ea83971132a7a00ca3195cfe29a15461223b8be42d17ff7eca6fabfa98e25202

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1.tar.gz:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: colstore-0.3.1-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 187.0 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for colstore-0.3.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 e4c62bccf4f843788f34242ab6d645181b8edfe603e26d8a68e3a6e54a04e387
MD5 3b418addefe1744f4a30e5d0726b26e6
BLAKE2b-256 691f82cdf4922b4bc11ee9eca2925ca0a283201c58d9a7236a45d84984618432

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp313-cp313-win_amd64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for colstore-0.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4d5dad15e4c729b353f682e0b6097eef778d59a5a1f65121093838e3c25abd9f
MD5 a25be0ddccd8ad4e2360a1f6518ec9bc
BLAKE2b-256 4a457bfba6b07f059e1a039be09ca361850ff57453a6c0efd6ba917da529f545

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for colstore-0.3.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 756743da1ba2202fd37e4a139dcafa6fe62236051c039900c3965dd0bac45634
MD5 47dc74e320bce39c056c1e095ac38cf6
BLAKE2b-256 5becbe8a394f86379e2aa1394500c36924ac68bda9f92ba2f65118814d5a7db7

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: colstore-0.3.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 187.3 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for colstore-0.3.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 c42e1e73025f4f4ef473c696b07075d2e5509fa5173159bb8adfadaf251d59b8
MD5 a18cbae86996e51ce18f155ab424ad73
BLAKE2b-256 4d26d598f99f9bbdc18a70d98550b6c33193299a3c190ebb2052a009f89395d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp312-cp312-win_amd64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for colstore-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4c3aaa5a3da54f757f282003bb9b3a980876b721e71d8fd62d459c5efbddd867
MD5 69c1f161ec18ab555fdd2372c349e045
BLAKE2b-256 a7363b9baf76117376a7b467903c6e822b5e49cd4968cbfe8c2b6e4c5210be6d

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for colstore-0.3.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c8e6248930d519f601410fc51fbc2fcab6a27035e3e088cd611142347f14f40e
MD5 8c4269574aa01f66b0bc049e341907df
BLAKE2b-256 5b4920475ced67bf6f1708f1cec3a1423491b71c5a4789f1e51b506c3e19da8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: colstore-0.3.1-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 187.7 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for colstore-0.3.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 4c929bf38805eeb3f9a7844cc05355b820a42171f85897693969fd89f856cf64
MD5 4773c5ca72304198ee74f5d81c2f96bd
BLAKE2b-256 a9bf840f3fe271abcf61fd2b9686741fd5d8e85a7dc71507e87a5b915b5b68a8

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp311-cp311-win_amd64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for colstore-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2b5a54895811b808a2d57e7088d8306211b2c58ad8cda69bca8cf56bcd416e34
MD5 2161597f8ddbdc513f2a2ef4e044c27b
BLAKE2b-256 4beb0b58def8cb0974b09c65a33af0f5d0eca4a077ce3518cb89151ca6b20777

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for colstore-0.3.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 94b0aae0dea026f7ad3c1a4986a0add181eaec85045819a7d7c568f0bb12e25e
MD5 9386b33a639eb50e317a6ecaccc24eac
BLAKE2b-256 ebab9705e7d02565ef3a209879c06a70ea5228ba74e4c8433e85f9b5d16cc035

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: colstore-0.3.1-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 187.7 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for colstore-0.3.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 732851b22fdee7133ddbed34e83a05747da2f8cc173b2b8e77fdb75cbbed6390
MD5 7180c4958d5fef999258098c52ccf0ad
BLAKE2b-256 667c377e0435d8803b31800d074465192b16b520189d4452f574bcd395a18593

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp310-cp310-win_amd64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for colstore-0.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 617cff6c5a76459282da264973cffcab69208dd77f5cbc3fdae5db8475252f49
MD5 63881560eb01544ec833246626b54394
BLAKE2b-256 3731921b60b0f90a9ffd783e4f3efe8328c163a2a05db1e66b33e674dd1dbcdb

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file colstore-0.3.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for colstore-0.3.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 526030e7e59818e490c91ed60965b33f7d4b445899a2117ae77226d8349fab58
MD5 d7ac613cb16bbe1605ee4f5bf5dca98f
BLAKE2b-256 4fd9b5a561a2d412430c6fdb6f26036da0e5357117c39f57e59965364e5f1233

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.1-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: release.yml on AlkaidCheng/colstore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page