Skip to content

Conversation

@shauneccles
Copy link

Improve GIL management during resampling operations to prevent blocking and enhance performance. Update error handling to manage exceptions more effectively, particularly in callback scenarios. Adjust the expected output size to accommodate additional frames introduced by #22 and remove support for Python 3.8. Update license specification format.

The latter changes are from existing community PRs that have already been merged.

@shauneccles
Copy link
Author

shauneccles commented Nov 19, 2025

For reference this is the results of the asyncio and threading test on my local machine.

PS C:\Users\shaun\python-samplerate-ledfx> uv run pytest tests/test_asyncio_performance.py -s
Uninstalled 1 package in 8ms
Installed 1 package in 10ms
================================================================ test session starts =================================================================
platform win32 -- Python 3.11.9, pytest-9.0.1, pluggy-1.6.0
rootdir: C:\Users\shaun\python-samplerate-ledfx
configfile: pyproject.toml
plugins: asyncio-1.3.0
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 28 items                                                                                                                                    

tests\test_asyncio_performance.py
default loop - sinc_fastest async with ThreadPoolExecutor (2 concurrent):
  Sequential: 0.0501s
  Parallel: 0.0259s
  Speedup: 1.93x
  Platform: AMD64
  ✓ Performance meets expectations (1.1x)
.
default loop - sinc_fastest async with ThreadPoolExecutor (4 concurrent):
  Sequential: 0.0993s
  Parallel: 0.0259s
  Speedup: 3.84x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
default loop - sinc_fastest async with ThreadPoolExecutor (8 concurrent):
  Sequential: 0.1991s
  Parallel: 0.0302s
  Speedup: 6.60x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
default loop - sinc_medium async with ThreadPoolExecutor (2 concurrent):
  Sequential: 0.0987s
  Parallel: 0.0495s
  Speedup: 1.99x
  Platform: AMD64
  ✓ Performance meets expectations (1.1x)
.
default loop - sinc_medium async with ThreadPoolExecutor (4 concurrent):
  Sequential: 0.1959s
  Parallel: 0.0504s
  Speedup: 3.89x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
default loop - sinc_medium async with ThreadPoolExecutor (8 concurrent):
  Sequential: 0.3948s
  Parallel: 0.0660s
  Speedup: 5.98x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
default loop - sinc_best async with ThreadPoolExecutor (2 concurrent):
  Sequential: 0.3053s
  Parallel: 0.1604s
  Speedup: 1.90x
  Platform: AMD64
  ✓ Performance meets expectations (1.1x)
.
default loop - sinc_best async with ThreadPoolExecutor (4 concurrent):
  Sequential: 0.6138s
  Parallel: 0.1547s
  Speedup: 3.97x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
default loop - sinc_best async with ThreadPoolExecutor (8 concurrent):
  Sequential: 1.2228s
  Parallel: 0.1897s
  Speedup: 6.44x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
winloop loop - sinc_fastest async with ThreadPoolExecutor (2 concurrent):
  Sequential: 0.0499s
  Parallel: 0.0257s
  Speedup: 1.94x
  Platform: AMD64
  ✓ Performance meets expectations (1.1x)
.
winloop loop - sinc_fastest async with ThreadPoolExecutor (4 concurrent):
  Sequential: 0.1001s
  Parallel: 0.0392s
  Speedup: 2.55x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
winloop loop - sinc_fastest async with ThreadPoolExecutor (8 concurrent):
  Sequential: 0.1988s
  Parallel: 0.0373s
  Speedup: 5.33x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
winloop loop - sinc_medium async with ThreadPoolExecutor (2 concurrent):
  Sequential: 0.0979s
  Parallel: 0.0495s
  Speedup: 1.98x
  Platform: AMD64
  ✓ Performance meets expectations (1.1x)
.
winloop loop - sinc_medium async with ThreadPoolExecutor (4 concurrent):
  Sequential: 0.1960s
  Parallel: 0.0576s
  Speedup: 3.40x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
winloop loop - sinc_medium async with ThreadPoolExecutor (8 concurrent):
  Sequential: 0.3957s
  Parallel: 0.0548s
  Speedup: 7.22x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
winloop loop - sinc_best async with ThreadPoolExecutor (2 concurrent):
  Sequential: 0.3051s
  Parallel: 0.1530s
  Speedup: 1.99x
  Platform: AMD64
  ✓ Performance meets expectations (1.1x)
.
winloop loop - sinc_best async with ThreadPoolExecutor (4 concurrent):
  Sequential: 0.6071s
  Parallel: 0.1605s
  Speedup: 3.78x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
winloop loop - sinc_best async with ThreadPoolExecutor (8 concurrent):
  Sequential: 1.2146s
  Parallel: 0.1851s
  Speedup: 6.56x
  Platform: AMD64
  ✓ Performance meets expectations (1.2x)
.
default loop - sinc_fastest blocking vs executor:
  Without executor (blocks loop): 0.0100s
  With ThreadPoolExecutor: 0.0057s
  Improvement: 1.77x
  ✓ Executor performance meets expectations
.
winloop loop - sinc_fastest blocking vs executor:
  Without executor (blocks loop): 0.0100s
  With ThreadPoolExecutor: 0.0056s
  Improvement: 1.80x
  ✓ Executor performance meets expectations
.
default loop - 2 concurrent tasks - ThreadPool vs ProcessPool:
  ThreadPoolExecutor: 0.0106s
  ProcessPoolExecutor: 0.1737s
  Ratio: 16.39x
  → ThreadPool is faster
    (GIL release makes ThreadPool competitive with ProcessPool)
.
default loop - 4 concurrent tasks - ThreadPool vs ProcessPool:
  ThreadPoolExecutor: 0.0109s
  ProcessPoolExecutor: 0.1873s
  Ratio: 17.14x
  → ThreadPool is faster
    (GIL release makes ThreadPool competitive with ProcessPool)
.
winloop loop - 2 concurrent tasks - ThreadPool vs ProcessPool:
  ThreadPoolExecutor: 0.0105s
  ProcessPoolExecutor: 0.1676s
  Ratio: 16.04x
  → ThreadPool is faster
    (GIL release makes ThreadPool competitive with ProcessPool)
.
winloop loop - 4 concurrent tasks - ThreadPool vs ProcessPool:
  ThreadPoolExecutor: 0.0110s
  ProcessPoolExecutor: 0.1850s
  Ratio: 16.89x
  → ThreadPool is faster
    (GIL release makes ThreadPool competitive with ProcessPool)
.
default loop - Mixed I/O and CPU workload:
  Total time: 0.1966s
  Tasks completed: 5
  ✓ Performance meets expectations (< 0.35s)
.
winloop loop - Mixed I/O and CPU workload:
  Total time: 0.2021s
  Tasks completed: 5
  ✓ Performance meets expectations (< 0.35s)
.
======================================================================
Asyncio Performance Report
======================================================================

Test Configuration:
  Sample rate: 44100 Hz
  Duration: 5.0 seconds (220500 samples)
  Conversion ratio: 2.0x
  Executor: ThreadPoolExecutor

----------------------------------------------------------------------
Converter: sinc_fastest
----------------------------------------------------------------------
  1 concurrent task (baseline):
    Execution time: 0.0253s
  2 concurrent tasks:
    Parallel execution time: 0.0254s
    Equivalent sequential time: 0.0507s (2 × 0.0253s)
    Speedup: 2.00x
    Parallel efficiency: 99.9%
  4 concurrent tasks:
    Parallel execution time: 0.0265s
    Equivalent sequential time: 0.1013s (4 × 0.0253s)
    Speedup: 3.82x
    Parallel efficiency: 95.6%

----------------------------------------------------------------------
Converter: sinc_medium
----------------------------------------------------------------------
  1 concurrent task (baseline):
    Execution time: 0.0493s
  2 concurrent tasks:
    Parallel execution time: 0.0497s
    Equivalent sequential time: 0.0985s (2 × 0.0493s)
    Speedup: 1.98x
    Parallel efficiency: 99.2%
  4 concurrent tasks:
    Parallel execution time: 0.0506s
    Equivalent sequential time: 0.1970s (4 × 0.0493s)
    Speedup: 3.90x
    Parallel efficiency: 97.4%

----------------------------------------------------------------------
Converter: sinc_best
----------------------------------------------------------------------
  1 concurrent task (baseline):
    Execution time: 0.1524s
  2 concurrent tasks:
    Parallel execution time: 0.1530s
    Equivalent sequential time: 0.3049s (2 × 0.1524s)
    Speedup: 1.99x
    Parallel efficiency: 99.6%
  4 concurrent tasks:
    Parallel execution time: 0.1579s
    Equivalent sequential time: 0.6098s (4 × 0.1524s)
    Speedup: 3.86x
    Parallel efficiency: 96.5%
.
======================================================================
Asyncio Performance Report
======================================================================

Test Configuration:
  Sample rate: 44100 Hz
  Duration: 5.0 seconds (220500 samples)
  Conversion ratio: 2.0x
  Executor: ThreadPoolExecutor

----------------------------------------------------------------------
Converter: sinc_fastest
----------------------------------------------------------------------
  1 concurrent task (baseline):
    Execution time: 0.0253s
  2 concurrent tasks:
    Parallel execution time: 0.0290s
    Equivalent sequential time: 0.0505s (2 × 0.0253s)
    Speedup: 1.74x
    Parallel efficiency: 87.2%
  4 concurrent tasks:
    Parallel execution time: 0.0264s
    Equivalent sequential time: 0.1010s (4 × 0.0253s)
    Speedup: 3.83x
    Parallel efficiency: 95.9%

----------------------------------------------------------------------
Converter: sinc_medium
----------------------------------------------------------------------
  1 concurrent task (baseline):
    Execution time: 0.0497s
  2 concurrent tasks:
    Parallel execution time: 0.0579s
    Equivalent sequential time: 0.0995s (2 × 0.0497s)
    Speedup: 1.72x
    Parallel efficiency: 85.9%
  4 concurrent tasks:
    Parallel execution time: 0.0609s
    Equivalent sequential time: 0.1990s (4 × 0.0497s)
    Speedup: 3.27x
    Parallel efficiency: 81.7%

----------------------------------------------------------------------
Converter: sinc_best
----------------------------------------------------------------------
  1 concurrent task (baseline):
    Execution time: 0.1542s
  2 concurrent tasks:
    Parallel execution time: 0.1538s
    Equivalent sequential time: 0.3083s (2 × 0.1542s)
    Speedup: 2.00x
    Parallel efficiency: 100.2%
  4 concurrent tasks:
    Parallel execution time: 0.1596s
    Equivalent sequential time: 0.6167s (4 × 0.1542s)
    Speedup: 3.86x
    Parallel efficiency: 96.6%
PS C:\Users\shaun\python-samplerate-ledfx> uv run pytest .\tests\test_threading_performance.py -s
================================================================ test session starts =================================================================
platform win32 -- Python 3.11.9, pytest-9.0.1, pluggy-1.6.0
rootdir: C:\Users\shaun\python-samplerate-ledfx
configfile: pyproject.toml
plugins: asyncio-1.3.0
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 38 items                                                                                                                                    

tests\test_threading_performance.py
sinc_fastest with 2 threads:
  Sequential: 0.0500s
  Parallel: 0.0259s
  Speedup: 1.93x
  Platform: AMD64
  Individual thread times: ['0.0248s', '0.0248s']
  ✓ Performance meets expectations (1.2x)
.
sinc_fastest with 4 threads:
  Sequential: 0.0995s
  Parallel: 0.0258s
  Speedup: 3.86x
  Platform: AMD64
  Individual thread times: ['0.0251s', '0.0249s', '0.0249s', '0.0249s']
  ✓ Performance meets expectations (1.35x)
.
sinc_fastest with 6 threads:
  Sequential: 0.1492s
  Parallel: 0.0364s
  Speedup: 4.10x
  Platform: AMD64
  Individual thread times: ['0.0318s', '0.0293s', '0.0356s', '0.0252s', '0.0253s', '0.0250s']
  ✓ Performance meets expectations (1.35x)
.
sinc_fastest with 8 threads:
  Sequential: 0.2029s
  Parallel: 0.0353s
  Speedup: 5.74x
  Platform: AMD64
  Individual thread times: ['0.0248s', '0.0248s', '0.0248s', '0.0278s', '0.0344s', '0.0318s', '0.0249s', '0.0248s']
  ✓ Performance meets expectations (1.35x)
.
sinc_medium with 2 threads:
  Sequential: 0.0979s
  Parallel: 0.0576s
  Speedup: 1.70x
  Platform: AMD64
  Individual thread times: ['0.0570s', '0.0572s']
  ✓ Performance meets expectations (1.2x)
.
sinc_medium with 4 threads:
  Sequential: 0.1957s
  Parallel: 0.0590s
  Speedup: 3.32x
  Platform: AMD64
  Individual thread times: ['0.0576s', '0.0584s', '0.0506s', '0.0500s']
  ✓ Performance meets expectations (1.35x)
.
sinc_medium with 6 threads:
  Sequential: 0.2950s
  Parallel: 0.0629s
  Speedup: 4.69x
  Platform: AMD64
  Individual thread times: ['0.0614s', '0.0624s', '0.0508s', '0.0503s', '0.0518s', '0.0494s']
  ✓ Performance meets expectations (1.35x)
.
sinc_medium with 8 threads:
  Sequential: 0.3993s
  Parallel: 0.0635s
  Speedup: 6.29x
  Platform: AMD64
  Individual thread times: ['0.0588s', '0.0593s', '0.0628s', '0.0551s', '0.0502s', '0.0603s', '0.0596s', '0.0616s']
  ✓ Performance meets expectations (1.35x)
.
sinc_best with 2 threads:
  Sequential: 0.3043s
  Parallel: 0.1603s
  Speedup: 1.90x
  Platform: AMD64
  Individual thread times: ['0.1600s', '0.1583s']
  ✓ Performance meets expectations (1.2x)
.
sinc_best with 4 threads:
  Sequential: 0.6091s
  Parallel: 0.1609s
  Speedup: 3.78x
  Platform: AMD64
  Individual thread times: ['0.1605s', '0.1572s', '0.1548s', '0.1527s']
  ✓ Performance meets expectations (1.35x)
.
sinc_best with 6 threads:
  Sequential: 0.9121s
  Parallel: 0.1678s
  Speedup: 5.43x
  Platform: AMD64
  Individual thread times: ['0.1520s', '0.1667s', '0.1619s', '0.1626s', '0.1535s', '0.1667s']
  ✓ Performance meets expectations (1.35x)
.
sinc_best with 8 threads:
  Sequential: 1.2174s
  Parallel: 0.1758s
  Speedup: 6.93x
  Platform: AMD64
  Individual thread times: ['0.1559s', '0.1645s', '0.1569s', '0.1597s', '0.1551s', '0.1746s', '0.1643s', '0.1612s']
  ✓ Performance meets expectations (1.35x)
.
sinc_fastest Resampler.process() with 2 threads:
  Sequential: 0.0499s
  Parallel: 0.0254s
  Speedup: 1.96x
  Platform: AMD64
  Individual thread times: ['0.0249s', '0.0249s']
  ✓ Performance meets expectations (1.1x)
.
sinc_fastest Resampler.process() with 4 threads:
  Sequential: 0.1001s
  Parallel: 0.0264s
  Speedup: 3.79x
  Platform: AMD64
  Individual thread times: ['0.0252s', '0.0251s', '0.0257s', '0.0252s']
  ✓ Performance meets expectations (1.25x)
.
sinc_fastest Resampler.process() with 6 threads:
  Sequential: 0.1502s
  Parallel: 0.0323s
  Speedup: 4.65x
  Platform: AMD64
  Individual thread times: ['0.0249s', '0.0311s', '0.0249s', '0.0250s', '0.0313s', '0.0249s']
  ✓ Performance meets expectations (1.25x)
.
sinc_fastest Resampler.process() with 8 threads:
  Sequential: 0.2012s
  Parallel: 0.0271s
  Speedup: 7.41x
  Platform: AMD64
  Individual thread times: ['0.0248s', '0.0251s', '0.0255s', '0.0249s', '0.0250s', '0.0250s', '0.0254s', '0.0253s']
  ✓ Performance meets expectations (1.25x)
.
sinc_medium Resampler.process() with 2 threads:
  Sequential: 0.0981s
  Parallel: 0.0495s
  Speedup: 1.98x
  Platform: AMD64
  Individual thread times: ['0.0489s', '0.0491s']
  ✓ Performance meets expectations (1.1x)
.
sinc_medium Resampler.process() with 4 threads:
  Sequential: 0.1961s
  Parallel: 0.0506s
  Speedup: 3.88x
  Platform: AMD64
  Individual thread times: ['0.0488s', '0.0489s', '0.0489s', '0.0497s']
  ✓ Performance meets expectations (1.25x)
.
sinc_medium Resampler.process() with 6 threads:
  Sequential: 0.2939s
  Parallel: 0.0510s
  Speedup: 5.77x
  Platform: AMD64
  Individual thread times: ['0.0489s', '0.0489s', '0.0488s', '0.0492s', '0.0497s', '0.0490s']
  ✓ Performance meets expectations (1.25x)
.
sinc_medium Resampler.process() with 8 threads:
  Sequential: 0.3920s
  Parallel: 0.0575s
  Speedup: 6.81x
  Platform: AMD64
  Individual thread times: ['0.0494s', '0.0491s', '0.0493s', '0.0494s', '0.0499s', '0.0558s', '0.0498s', '0.0558s']
  ✓ Performance meets expectations (1.25x)
.
sinc_best Resampler.process() with 2 threads:
  Sequential: 0.3049s
  Parallel: 0.1525s
  Speedup: 2.00x
  Platform: AMD64
  Individual thread times: ['0.1521s', '0.1519s']
  ✓ Performance meets expectations (1.1x)
.
sinc_best Resampler.process() with 4 threads:
  Sequential: 0.6109s
  Parallel: 0.1683s
  Speedup: 3.63x
  Platform: AMD64
  Individual thread times: ['0.1580s', '0.1537s', '0.1675s', '0.1623s']
  ✓ Performance meets expectations (1.25x)
.
sinc_best Resampler.process() with 6 threads:
  Sequential: 0.9163s
  Parallel: 0.1729s
  Speedup: 5.30x
  Platform: AMD64
  Individual thread times: ['0.1599s', '0.1709s', '0.1721s', '0.1651s', '0.1653s', '0.1574s']
  ✓ Performance meets expectations (1.25x)
.
sinc_best Resampler.process() with 8 threads:
  Sequential: 1.2241s
  Parallel: 0.1809s
  Speedup: 6.77x
  Platform: AMD64
  Individual thread times: ['0.1600s', '0.1637s', '0.1769s', '0.1727s', '0.1661s', '0.1792s', '0.1726s', '0.1598s']
  ✓ Performance meets expectations (1.25x)
.
sinc_fastest CallbackResampler with 2 threads:
  Sequential: 0.0504s
  Parallel: 0.0258s
  Speedup: 1.95x
  Platform: AMD64
  Individual thread times: ['0.0251s', '0.0252s']
  ✓ Performance meets expectations (1.2x)
.
sinc_fastest CallbackResampler with 4 threads:
  Sequential: 0.1012s
  Parallel: 0.0267s
  Speedup: 3.79x
  Platform: AMD64
  Individual thread times: ['0.0258s', '0.0254s', '0.0258s', '0.0258s']
  ✓ Performance meets expectations (1.2x)
.
sinc_fastest CallbackResampler with 6 threads:
  Sequential: 0.1523s
  Parallel: 0.0273s
  Speedup: 5.58x
  Platform: AMD64
  Individual thread times: ['0.0270s', '0.0252s', '0.0257s', '0.0256s', '0.0256s', '0.0258s']
  ✓ Performance meets expectations (1.2x)
.
sinc_fastest CallbackResampler with 8 threads:
  Sequential: 0.2013s
  Parallel: 0.0404s
  Speedup: 4.99x
  Platform: AMD64
  Individual thread times: ['0.0261s', '0.0397s', '0.0397s', '0.0261s', '0.0252s', '0.0255s', '0.0256s', '0.0260s']
  ✓ Performance meets expectations (1.2x)
.
sinc_medium CallbackResampler with 2 threads:
  Sequential: 0.0985s
  Parallel: 0.0499s
  Speedup: 1.97x
  Platform: AMD64
  Individual thread times: ['0.0491s', '0.0495s']
  ✓ Performance meets expectations (1.2x)
.
sinc_medium CallbackResampler with 4 threads:
  Sequential: 0.1970s
  Parallel: 0.0593s
  Speedup: 3.32x
  Platform: AMD64
  Individual thread times: ['0.0585s', '0.0588s', '0.0513s', '0.0495s']
  ✓ Performance meets expectations (1.2x)
.
sinc_medium CallbackResampler with 6 threads:
  Sequential: 0.2957s
  Parallel: 0.0554s
  Speedup: 5.34x
  Platform: AMD64
  Individual thread times: ['0.0539s', '0.0495s', '0.0495s', '0.0495s', '0.0541s', '0.0495s']
  ✓ Performance meets expectations (1.2x)
.
sinc_medium CallbackResampler with 8 threads:
  Sequential: 0.3935s
  Parallel: 0.0775s
  Speedup: 5.08x
  Platform: AMD64
  Individual thread times: ['0.0772s', '0.0696s', '0.0517s', '0.0592s', '0.0596s', '0.0503s', '0.0567s', '0.0668s']
  ✓ Performance meets expectations (1.2x)
.
sinc_best CallbackResampler with 2 threads:
  Sequential: 0.3054s
  Parallel: 0.1529s
  Speedup: 2.00x
  Platform: AMD64
  Individual thread times: ['0.1525s', '0.1521s']
  ✓ Performance meets expectations (1.2x)
.
sinc_best CallbackResampler with 4 threads:
  Sequential: 0.6106s
  Parallel: 0.1574s
  Speedup: 3.88x
  Platform: AMD64
  Individual thread times: ['0.1570s', '0.1566s', '0.1561s', '0.1524s']
  ✓ Performance meets expectations (1.2x)
.
sinc_best CallbackResampler with 6 threads:
  Sequential: 0.9167s
  Parallel: 0.1798s
  Speedup: 5.10x
  Platform: AMD64
  Individual thread times: ['0.1712s', '0.1751s', '0.1734s', '0.1787s', '0.1548s', '0.1551s']
  ✓ Performance meets expectations (1.2x)
.
sinc_best CallbackResampler with 8 threads:
  Sequential: 1.2261s
  Parallel: 0.1708s
  Speedup: 7.18x
  Platform: AMD64
  Individual thread times: ['0.1645s', '0.1572s', '0.1671s', '0.1557s', '0.1639s', '0.1564s', '0.1682s', '0.1685s']
  ✓ Performance meets expectations (1.2x)
..
======================================================================
GIL Release Performance Report
======================================================================

Test Configuration:
  Sample rate: 44100 Hz
  Duration: 5.0 seconds (220500 samples)
  Conversion ratio: 2.0x

----------------------------------------------------------------------
Converter: sinc_fastest
----------------------------------------------------------------------
  1 thread (baseline):
    Execution time: 0.0249s
  2 threads (parallel):
    Parallel execution time: 0.0256s
    Equivalent sequential time: 0.0498s (2 × 0.0249s)
    Speedup: 1.95x
    Parallel efficiency: 97.3%
    Avg thread time: 0.0250s
  4 threads (parallel):
    Parallel execution time: 0.0257s
    Equivalent sequential time: 0.0995s (4 × 0.0249s)
    Speedup: 3.87x
    Parallel efficiency: 96.8%
    Avg thread time: 0.0249s

----------------------------------------------------------------------
Converter: sinc_medium
----------------------------------------------------------------------
  1 thread (baseline):
    Execution time: 0.0491s
  2 threads (parallel):
    Parallel execution time: 0.0494s
    Equivalent sequential time: 0.0981s (2 × 0.0491s)
    Speedup: 1.98x
    Parallel efficiency: 99.2%
    Avg thread time: 0.0489s
  4 threads (parallel):
    Parallel execution time: 0.0505s
    Equivalent sequential time: 0.1962s (4 × 0.0491s)
    Speedup: 3.89x
    Parallel efficiency: 97.2%
    Avg thread time: 0.0496s

----------------------------------------------------------------------
Converter: sinc_best
----------------------------------------------------------------------
  1 thread (baseline):
    Execution time: 0.1527s
  2 threads (parallel):
    Parallel execution time: 0.1534s
    Equivalent sequential time: 0.3055s (2 × 0.1527s)
    Speedup: 1.99x
    Parallel efficiency: 99.6%
    Avg thread time: 0.1529s
  4 threads (parallel):
    Parallel execution time: 0.1532s
    Equivalent sequential time: 0.6110s (4 × 0.1527s)
    Speedup: 3.99x
    Parallel efficiency: 99.7%
    Avg thread time: 0.1524s

Looking at #32 which has same tests on same machine at (about) the same time the headlines from this PR is:

  • Releasing the GIL is a very good thing
    • Basically a linear performance improvement with more threads/concurrency
  • Asyncio + ThreadPoolExecutor is probably the way to go for concurrent resampling

Copy link
Collaborator

@fakufaku fakufaku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty good to me. Please just sync with master.
Would it make sense to combine this with your other PR that contains the tests?

matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
python-version: [3.9, "3.10", "3.11", "3.12", "3.13", "3.14"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been merged already. Could you please sync with master?

#endif

// This value was empirically and somewhat arbitrarily chosen; increase it for further safety.
#define END_OF_INPUT_EXTRA_OUTPUT_FRAMES 10000
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add some more details about what this constant controls?

// be more than the expected number of output samples during mid-stream
// steady-state processing. (Also, when the stream is started, the number
// of output samples generated will generally be zero or otherwise less
// than the number of samples in mid-stream processing.)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a maximum we could expect?

output.resize(out_shape);
} else if ((size_t)output_frames_gen >= new_size) {
// This means our fudge factor is too small.
throw std::runtime_error("Generated more output samples than expected!");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than failing, is it possible to truncate the output?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants