Skip to main content

A Python module to improve performance of multiprocessing queues

Project description

Install

pip install turbo-queue

Project Status

WIP - Not ready for PRs yet

Turbo Queue

Build a high performance data-pipeline with Turbo Queue. A pure Python, shared nothing, multi-processing queue, that works across child processes, and even between individual Python applications!

Contents

Overview

Turbo Queue is used in place of the Python Multiprocessing Queue with simple add/get semantics, allowing you to create multiple processes that share a queue.

Turbo Queue was designed to improve performance in situations where the Python Multiprocessing Queues is typically used. We found that as the number of processes subscribed to a single Multiprocessing Queue increased, the performance improvement on each successive process decreased. This appeared to be due to contention, with the processes locking/unlocking the queue to load/get data.

Use Cases

  • Stream data from Kafka, run CPU intensive operations on the data, and then stream back to Kafka, on the order of billions of events per day.
  • Stream data from Kafka, reformat, and send to Elasticsearch.
  • Stream data from Kafka, reformat, and send to a service API.
  • Pull data from an API at high volume, process, and send to another API.

Solution

Our solution was to develop the Turbo Queue class. It is a shared nothing "queue" that uses the file system to provide the basis for coordination between the process. We use an agreed upon set of rules (as defined in the class) to create and manage files to store and process the data. SQLite is used a high-performance file storage format. File names (and re-naming) are used as the control mechanisms. In our use case we work in batches of data, and that is utilized here as well. We allow tuning of the batch size (which equates to the rows in the SQLite file) for optimal performance. A side benefit of the shared nothing approach allows entirely separate applications (not just sub-processes) to use the queue.

Results

Before Turbo Queue, using the built-in Multiprocessing Queue resulted in diminishing returns with 3 or more processes. While performance increased with each process, the throughput was not well correlated to the number of processes.

However, with Turbo Queue, we were able to max out our processors on a single system(40+) with a substantial throughput increase. We began to hit limitations with our network and Kafka stack. In one instance, we were able to reduce our requirements from 40 python applications (running 2 subprocesses each), to 2 python apps with 30 subprocesses.

Will this help you?

YMMV. This worked well for our use case: CPU intensive processes, moving large volumes of data to and from Kafka and other services, and CPU dense hardware.

Quickstart

A very basic example:

import turbo_queue

queue_name = 'data_in'
root_path = '/path/to/queue'

### cleanup queues from pervious restarts
clean_turbo_queue = turbo_queue.Startup()
clean_turbo_queue.queue_name = queue_name
clean_turbo_queue.root_path = root_path
clean_turbo_queue.on_start_cleanup()

### enqueue data  
enqueue = turbo_queue.Enqueue()
enqueue.queue_name = queue_name
enqueue.root_path = root_path
enqueue.max_ready_files = 5
enqueue.max_events_per_file = 1000
enqueue.start()

enqueue.update_enqueue_active_state()
while enqueue.enqueue_active:
  data = """{"data":"add_to_queue"}"""
  enqueue.add(data)
  enqueue.update_enqueue_active_state()
  # update_enqueue_active_state needs to be run at some frequency
  # if the number of ready files exceeds the max, the state will will be set to False
  # this is the mechanism used to address downstream backup in the queue

# example function to process the data
def process_data(data)
  ### do something with the data
  return

### Dequeue data
dequeue = turbo_queue.Dequeue()
dequeue.queue_name = queue_name
dequeue.root_path = root_path
get_data = dequeue.get()
data = next(get_data)
while data:
  process_data(data)
  data = next(get_data)

# data = None when the queue is currently empty
# call next(get_data) again to check the queue for more data

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

turbo_queue-0.8.0.tar.gz (369.3 kB view details)

Uploaded Source

Built Distribution

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

turbo_queue-0.8.0-py3-none-any.whl (14.5 kB view details)

Uploaded Python 3

File details

Details for the file turbo_queue-0.8.0.tar.gz.

File metadata

  • Download URL: turbo_queue-0.8.0.tar.gz
  • Upload date:
  • Size: 369.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.2

File hashes

Hashes for turbo_queue-0.8.0.tar.gz
Algorithm Hash digest
SHA256 0a4166b8b72b065acde53f1b97915484b33f05f404bcf1e98d6f0df3ed04bbbf
MD5 de645b62bad8a3f3410d567fd5a7b00f
BLAKE2b-256 589b372e3cc76878f86d8caad3c90b900911dfa2f4a2db8279eb8d3a6643b676

See more details on using hashes here.

File details

Details for the file turbo_queue-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: turbo_queue-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 14.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.2

File hashes

Hashes for turbo_queue-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fe8e02f1528c5330a1e4c70743e84b4bbe52a486384abc98efa79f83c3905831
MD5 149db0a6cfeae18fd662a1b03798375d
BLAKE2b-256 e876c021cb79745a2e3301ca357c3345bdac40c1b402e68805127804c5fd1fc7

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