Skip to main content

Convenient threading with futures

Project description

threadlet

PyPI - Version PyPI - Python Version

More convenient threads and pools. With futures.

from threadlet import spawn, go


def plus2(n):
  return n + 2


# run function in thread
future = spawn(plus2, 1)
assert future.result() == 3

# run function in adaptive thread pool executor
future = go(plus2, 2)
assert future.result() == 4
  • spawn is a helper which runs function in a separate thread and returns Future.
  • go is a similar helper, but runs function in adaptive thread pool executor which is handled in background.
  • Task is a wrapper for encapsulating a function, its arguments and Future object.
  • Worker is a thread with a loop for executing incoming tasks.
  • SimpleThreadPoolExecutor is a simple variant of concurrent.futures.ThreadPoolExecutor which spawns all the threads at the beginning.
  • ThreadPoolExecutor is an adaptive variant of the concurrent.futures.ThreadPoolExecutor which automatically spawns and shutdowns threads depending on load. One thread in the pool lives forever, new threads are spawned on submit call if there are no idle threads and dies after some idle time(1 second by default).

Table of Contents

Installation

pip install threadlet

Usage

import threading
from threadlet import (
    spawn,
    go,
    Future,
    Task,
    Worker,
    SimpleThreadPoolExecutor,
    ThreadPoolExecutor,
)


def calc(x):
    return x * 2


# execute function in an adaptive thread pool executor
# which is going to be started automatically at first `go` call and shut down at application exit
future = go(calc, 2)
assert future.result() == 4
# is equivalent to:
with ThreadPoolExecutor() as tpe:
    future = tpe.submit(calc, 2)
    assert future.result() == 4

# execute function in a separate thread:
future = spawn(calc, 2)
assert future.result() == 4
# is equivalent to:
task = Task(Future(), calc, [2], {})
threading.Thread(target=task.run).start()
assert task.future.result() == 4

# spawns one thread(worker) to sequentially handle all submitted functions
with Worker() as w:
    f1 = w.submit(calc, 3)
    f2 = w.submit(calc, 4)
    assert f1.result() == 6
    assert f2.result() == 8

# spawns 4 threads(workers) to handle all tasks in parallel
with SimpleThreadPoolExecutor(4) as tpe:
    future = tpe.submit(calc, 5)
    assert future.result() == 10

Benchmarks

  • submit: submits 1 million futures.
  • e2e[N] (end to end[N workers]): submits 1 million futures using N workers and consumes results in a separate thread.
concurrent.futures.thread.ThreadPoolExecutor submit: time=12.94s size=0.04mb, peak=43.61mb
                threadlet.ThreadPoolExecutor submit: time= 2.89s size=0.04mb, peak=20.35mb
          threadlet.SimpleThreadPoolExecutor submit: time= 2.72s size=0.04mb, peak=24.49mb

concurrent.futures.thread.ThreadPoolExecutor e2e[1]: time=15.80s size=0.04mb, peak=28.56mb
                threadlet.ThreadPoolExecutor e2e[1]: time= 4.32s size=0.02mb, peak=19.48mb
          threadlet.SimpleThreadPoolExecutor e2e[1]: time= 4.23s size=0.02mb, peak=26.45mb

concurrent.futures.thread.ThreadPoolExecutor e2e[2]: time=33.36s size=0.07mb, peak=32.00mb
                threadlet.ThreadPoolExecutor e2e[2]: time= 4.35s size=0.02mb, peak=35.83mb
          threadlet.SimpleThreadPoolExecutor e2e[2]: time= 4.18s size=0.02mb, peak=41.81mb

concurrent.futures.thread.ThreadPoolExecutor e2e[4]: time= 7.49s size=0.11mb, peak=42.97mb
                threadlet.ThreadPoolExecutor e2e[4]: time= 4.37s size=0.03mb, peak=28.21mb
          threadlet.SimpleThreadPoolExecutor e2e[4]: time= 4.30s size=0.02mb, peak=39.81mb

concurrent.futures.thread.ThreadPoolExecutor e2e[8]: time= 7.30s size=0.21mb, peak=41.04mb
                threadlet.ThreadPoolExecutor e2e[8]: time= 4.49s size=0.05mb, peak=29.20mb
          threadlet.SimpleThreadPoolExecutor e2e[8]: time= 4.18s size=0.03mb, peak=38.36mb

License

threadlet is distributed under the terms of 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 Distribution

threadlet-3.1.1.tar.gz (8.6 kB view details)

Uploaded Source

Built Distribution

threadlet-3.1.1-py3-none-any.whl (5.5 kB view details)

Uploaded Python 3

File details

Details for the file threadlet-3.1.1.tar.gz.

File metadata

  • Download URL: threadlet-3.1.1.tar.gz
  • Upload date:
  • Size: 8.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.0 CPython/3.11.7

File hashes

Hashes for threadlet-3.1.1.tar.gz
Algorithm Hash digest
SHA256 cb03b0279cef211baf6804764ed54d4d3d2962fa198ef24b27d1d9a9274ef264
MD5 b0fa18928b74e7e33ba7d8b6ad67a29c
BLAKE2b-256 29fe9af44dd6e6efcb8e9edcebb13f87eb0b4c5cd36f6355f634e87da400ffe6

See more details on using hashes here.

File details

Details for the file threadlet-3.1.1-py3-none-any.whl.

File metadata

  • Download URL: threadlet-3.1.1-py3-none-any.whl
  • Upload date:
  • Size: 5.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.0 CPython/3.11.7

File hashes

Hashes for threadlet-3.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 821bcd2b8c7b16ca064817a1d085132dc32bebef4250e56e85e6653b25d25cf5
MD5 62d4d353cc5a46513599098d5059b97d
BLAKE2b-256 0014e7e53024f242faabf0a4a91e8ffa651366432c232a744cda45aeaed254d0

See more details on using hashes here.

Supported by

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