Skip to main content

A lightning-fast, zero-copy, cross-process data store for Python using Apache Arrow and shared memory.

Project description

ArrowShelf

🛑 Stop Pickling. 🚀 Start Sharing.

PyPI version Python Version License: MIT

ArrowShelf is a high-performance, zero-copy, cross-process data store for Python. It uses Apache Arrow and shared memory to eliminate the crippling overhead of pickle in multiprocessing workflows, allowing you to unlock the full power of your multi-core CPU for data science and analysis.


The Problem: Python's Multiprocessing Bottleneck

When using Python's multiprocessing library, sharing large DataFrames between processes is incredibly slow. Python must pickle the data, send the bytes over a pipe, and unpickle it in each child process. For gigabytes of data, this overhead can make your parallel code even slower than single-threaded code, wasting your time and your expensive hardware.

The ArrowShelf Solution: The Shared Memory Bookshelf

ArrowShelf runs a tiny, high-performance daemon (written in Rust) that coordinates access to data stored in shared memory. Instead of slowly sending a massive copy of your data to each process, you place it on the "shelf" once. Your worker processes can then read this data instantly with zero copy overhead.

The Analogy: Instead of photocopying a 1,000-page book for every colleague (the pickle way), you place the book on a magic, shared bookshelf and just tell them its location (ArrowShelf). Access is instantaneous.


🚀 Quick Start

1. Installation

pip install arrowshelf

2. Start the Server In your first terminal, start the ArrowShelf server. It will run in the foreground.

python -m arrowshelf.server

3. Run Your High-Performance Code In a second terminal, run your processing script. To get maximum performance, use arrowshelf.get_arrow() and compute directly with PyArrow's C++-backed functions.

import multiprocessing as mp
import pandas as pd
import numpy as np
import pyarrow.compute as pc # Import PyArrow's compute functions
import arrowshelf

def high_performance_worker(data_key):
    # 1. Get a zero-copy reference to the Arrow Table. This is instant.
    arrow_table = arrowshelf.get_arrow(data_key)
    
    # 2. Perform calculations directly on the Arrow data.
    #    This avoids the slow .to_pandas() step.
    result = pc.sum(arrow_table.column('value')).as_py()
    return result

if __name__ == "__main__":
    large_df = pd.DataFrame(np.random.rand(10_000_000, 1), columns=['value'])

    # 1. Put the data onto the shelf ONCE.
    data_key = arrowshelf.put(large_df)

    # 2. Pass only the tiny key string to the workers.
    with mp.Pool(processes=4) as pool:
        results = pool.map(high_performance_worker, [data_key] * 4)

    # 3. Clean up the data from the shelf.
    arrowshelf.delete(data_key)
    print("ArrowShelf processing complete!")

⚡ Real-World Example: process_data.py

To see the full power of ArrowShelf in action, we've included a complete, real-world example script in the examples/ directory. This script shows you how to:

  1. Load a large CSV file from disk.
  2. Use command-line arguments to control the number of CPU cores.
  3. Perform a complex parallel computation using ArrowShelf's high-performance native Arrow interface.
  4. Time the entire workflow and see the results.

How to Run the Example

1. Create a Large Sample Dataset (Optional)

If you don't have a large CSV file handy, you can create a 10-million-row sample file with this command:

# This will create the file 'my_big_data.csv' in your current directory
python examples/process_data.py --create-sample my_big_data.csv

2. Run the Processing Script Make sure your ArrowShelf server is running in another terminal (python -m arrowshelf.server). Then, run the script, telling it which file to process and how many cores to use.

# Process 'my_big_data.csv' using 8 CPU cores
python examples/process_data.py my_big_data.csv --cores 8

You will see a detailed output like this:

Loading data from 'my_big_data.csv'...
Successfully loaded DataFrame with 10,000,000 rows (381.47 MB).
Connecting to ArrowShelf server...
Connection successful.

Starting parallel processing on 8 cores...
 -> Data placed on shelf in 0.9123 seconds.
 -> Parallel computation finished in 2.5432 seconds.
----------------------------------------
✅ Total processing time: 3.4555 seconds
   Results from workers: [0.001, 0.001, ..., 0.001]
----------------------------------------

Cleaning up shared memory object from shelf...
Cleanup complete.

This script is the perfect starting point for adapting ArrowShelf to your own data processing pipelines.

⚡ Performance: The Proof is in the Numbers

ArrowShelf's power is most evident in two common, real-world scenarios: 1) parallel tasks on typical developer machines (2-8 cores), and 2) iterative workflows common in data science.

Scenario 1: Parallel Performance vs. CPU Core Count

This benchmark shows how ArrowShelf and pickle perform on a single, heavy computation task as we increase the number of CPU cores.

Test: A complex calculation on a 5,000,000 row DataFrame.

Num Cores Pickle Time (s) ArrowShelf Time (s) Speedup Factor
2 0.6882 0.5633 1.22x
4 0.7351 0.6419 1.15x
8 0.8925 0.8462 1.06x
12 1.0780 1.1506 0.94x

The Verdict & Analysis:

This data reveals a fascinating story about Python's performance limitations:

  1. ArrowShelf Excels at Low-to-Medium Core Counts: On standard developer machines (2-8 cores), ArrowShelf is significantly faster. It successfully eliminates the pickle data transfer bottleneck, allowing your cores to start their work sooner. This is the key advantage for the majority of users.

  2. The High-Core "GIL Bottleneck": As we scale to a very high number of cores (12+), the bottleneck of the application shifts away from data transfer and towards contention for Python's Global Interpreter Lock (GIL). At this point, the performance of all CPU-bound parallel Python code begins to suffer. For these highly-specialized, "all-at-once" CPU-bound tasks, the simpler "divide-and-conquer" approach of pickle can be more effective.

The takeaway is clear: For the most common parallel tasks on standard hardware, ArrowShelf provides a direct and significant speedup.

Scenario 2: The Iterative & Interactive Advantage

This benchmark simulates a data scientist in a Jupyter Notebook running 5 sequential parallel tasks on the same large dataset.

Test: 5 consecutive tasks on a 5,000,000 row DataFrame using 8 cores.

Workflow Total Time for 5 Tasks Breakdown
Pickle 4.59 s (Pays the full ~0.9s data transfer cost 5 times)
ArrowShelf 4.86 s (0.5s one-time put + 4.3s for all 5 tasks)

The Verdict:

This is where ArrowShelf becomes a revolutionary tool for productivity.

  • pickle is inefficient for interactive work, forcing you to wait for the slow data transfer on every single run.
  • ArrowShelf has a small, one-time setup cost. After that, every subsequent parallel task is blazingly fast.

For a real-world workflow with dozens of tasks, the initial setup cost becomes insignificant, and ArrowShelf provides a dramatically faster and more fluid development experience that pickle cannot match.



📖 API Reference

Function Description
arrowshelf.put(df) 📥 Stores a Pandas DataFrame on the shelf, returns a key.
arrowshelf.get(key) 📤 Retrieves a copy as a Pandas DataFrame (for convenience).
arrowshelf.get_arrow(key) 🚀 Retrieves a zero-copy reference as a PyArrow Table (for high-performance).
arrowshelf.delete(key) 🗑️ Removes an object from the shelf.
arrowshelf.list_keys() 📋 Returns a list of all keys on the shelf.

🔮 Future Roadmap

  • In-Server Querying (V3.0): Run SQL queries directly on the in-memory data via DataFusion.
  • Enhanced Data Types: Native support for NumPy arrays, Polars DataFrames, and more.

🤝 Contributing

Contributions are welcome! Please open an issue or submit a pull request on our GitHub repository.


📄 License

This project is licensed under the MIT License.

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

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

arrowshelf-2.2.4-py3-none-win_amd64.whl (831.6 kB view details)

Uploaded Python 3Windows x86-64

File details

Details for the file arrowshelf-2.2.4-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for arrowshelf-2.2.4-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 ed1d0ab95b0a2163fbf9bcf781bd4dbf2d23ea5a2a34e614ba718e43d428da6c
MD5 bbdd25d94394501bec5052e1fd10880e
BLAKE2b-256 1b8e445a142d30190a3813257468bb910817ec0d123cdb956411c508ff6c7778

See more details on using hashes here.

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