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.0.tar.gz (304.4 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.0-cp313-cp313-win_amd64.whl (173.2 kB view details)

Uploaded CPython 3.13Windows x86-64

colstore-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (290.0 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

colstore-0.3.0-cp313-cp313-macosx_11_0_arm64.whl (175.7 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

colstore-0.3.0-cp312-cp312-win_amd64.whl (173.5 kB view details)

Uploaded CPython 3.12Windows x86-64

colstore-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (292.4 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

colstore-0.3.0-cp312-cp312-macosx_11_0_arm64.whl (175.9 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

colstore-0.3.0-cp311-cp311-win_amd64.whl (173.9 kB view details)

Uploaded CPython 3.11Windows x86-64

colstore-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (292.1 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

colstore-0.3.0-cp311-cp311-macosx_11_0_arm64.whl (172.6 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

colstore-0.3.0-cp310-cp310-win_amd64.whl (174.0 kB view details)

Uploaded CPython 3.10Windows x86-64

colstore-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (291.7 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

colstore-0.3.0-cp310-cp310-macosx_11_0_arm64.whl (173.1 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: colstore-0.3.0.tar.gz
  • Upload date:
  • Size: 304.4 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.0.tar.gz
Algorithm Hash digest
SHA256 f835486d90a1fa6fd1ceba5f53fc64849646990fa202cdf4e8e24c7fa6bbf01e
MD5 d83811241e9490025170d3e78a0bea36
BLAKE2b-256 c4e21f4603c079512fd66beaa3261b2d4cf967cb6a1415e32f3af8437f7d7b17

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0.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.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: colstore-0.3.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 173.2 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.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 3c0c131c0c0ea2322f48f5c7d95a8bb3cc8d578f20bde3c172ee829262637a67
MD5 8604f1f624b7e30a2cfab6c5bbf64c8b
BLAKE2b-256 f121e89119ae42a2d6ac4fc09569771900f9b9d21adeecd33594099c9bcd360f

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for colstore-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fb9c7ebe3231f4ff433e0e57c195efb52af02575e907e1306201836476ec25dd
MD5 aed5fa932608d57a7d6959e8d61ad1ee
BLAKE2b-256 2c5ea5d76b03363dc7906212323b7f33f3066ec69c73f4c3c311857a4a5d1ed3

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for colstore-0.3.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 255ad47ab2d8929688121678d26174db90e5f644013b5c463ed343ca962ecf4f
MD5 c362b7f06dea9313261207e5e2d2f228
BLAKE2b-256 52a1d5762973d8739771840c052f617d673a6bf6417b187db98db6de99bac26d

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: colstore-0.3.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 173.5 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.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 1c3f34cf6dbd12453d37a553396445c7b5a850e4e5e4f7d6149806b5ae69ebf9
MD5 b41ca115b79960139d37fa9cf9a71a19
BLAKE2b-256 35516138c7566bed0bb36f8e6da951a082d5b2e3a316e65c8a7f592f502e16c3

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for colstore-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3efd12330962a0b21e0b6c627fe16915dae05d23fcf76829649e2457076c780e
MD5 fc0e109bd3754edcd08f8f7c63af3f32
BLAKE2b-256 c30e2eb442e2270c6f825f31b5f43c0d22d3bc2d1ec0c898c110d69257a64d47

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for colstore-0.3.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 24e40fbdc19d7b84232477ea343a205311c780993233ba4ec8bdb92228c508e8
MD5 90281e4245aabfdeb94f29f6cfec43f3
BLAKE2b-256 ab6337a1985a94ada39fb6426f8519b1736c31658987e8f360dd0afaabba2fa4

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: colstore-0.3.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 173.9 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.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 059f955e33198254cd432d20a5e4e63b6455d2566a1c2dda3040d4ffc9563e87
MD5 6d52615e30d62042e7b80f7e522b9659
BLAKE2b-256 61175a30ed106a682371fec0117f9c9f9b68766ca525a39d7c2815a7140305b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for colstore-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c3a73a0ddc32665cd39e975bd0496f1fb599a604ff834a818cca80b587973bd2
MD5 03b34d4a887ab272cedf19dca854680a
BLAKE2b-256 87a69c0e397ac2a2adf394350b4ff20ab67cb7cdf9e222685d51bfee05db91c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for colstore-0.3.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d9a76009f577917069a9b37d3a5c217a055d2b8afdf75964a1e9e488db262c67
MD5 2fcaca5d083a86eeade322f9a231c8c6
BLAKE2b-256 14b6a9faa61c46c54e0804c23d63db2bb0c51d8433d57bf1df9171436ec9f92c

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: colstore-0.3.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 174.0 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.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 73ff16aff96b5c9bc87174dde44dd519afa6bc89bbc197c2443e575342354980
MD5 714007b33cd56013762ffa2a109e40c1
BLAKE2b-256 9d0204295faf9afc6f374d5b28201371f82e1fd70a45ae9d4c25484cb8232509

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for colstore-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6bfa88c7b34f3f863d61a4376aae354123eae2bee2a8d195dc29aa0733395c61
MD5 bfae18fb7dcaab608bfd83cf86c276ca
BLAKE2b-256 a62b0a5bd96c2f3a8a70195396b78f010a0ac3530c18ef7a35e7af8d1aa0ddbe

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for colstore-0.3.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6b422442e2ddd5bcf3ed2052e08399f846389f3bacbb23e5c5bf77b137f51e02
MD5 a8b607160e2956ba60975d120d4d01e0
BLAKE2b-256 97f187381fb58786f1029c60516c6b91de95cd1fdcf01f1a04fa8200f50d090c

See more details on using hashes here.

Provenance

The following attestation bundles were made for colstore-0.3.0-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