• Jason Madden's avatar
    Speed up Greenlet creation on CPython · 760a080c
    Jason Madden authored
    Two ways: store tuples instead of _frame objects and use direct access
    to two of the attributes of the CPython frame objects.
    
    Benchmarks:
    
    +------------------------+-----------------+------------------------------+
    | Benchmark              | spawn_27_master | spawn_27_tuple2              |
    +========================+=================+==============================+
    | eventlet sleep         | 9.12 us         | 8.77 us: 1.04x faster (-4%)  |
    +------------------------+-----------------+------------------------------+
    | gevent spawn           | 14.5 us         | 13.2 us: 1.10x faster (-9%)  |
    +------------------------+-----------------+------------------------------+
    | gevent sleep           | 1.63 us         | 1.86 us: 1.14x slower (+14%) |
    +------------------------+-----------------+------------------------------+
    | geventpool spawn       | 30.4 us         | 23.6 us: 1.29x faster (-22%) |
    +------------------------+-----------------+------------------------------+
    | geventpool sleep       | 4.30 us         | 4.55 us: 1.06x slower (+6%)  |
    +------------------------+-----------------+------------------------------+
    | geventpool join        | 1.70 us         | 1.83 us: 1.08x slower (+8%)  |
    +------------------------+-----------------+------------------------------+
    | gevent spawn kwarg     | 16.5 us         | 13.5 us: 1.22x faster (-18%) |
    +------------------------+-----------------+------------------------------+
    | geventpool spawn kwarg | 30.5 us         | 23.9 us: 1.27x faster (-22%) |
    +------------------------+-----------------+------------------------------+
    
    Not significant (7): eventlet spawn; geventraw spawn; geventraw sleep;
    none spawn; eventlet spawn kwarg; geventraw spawn kwarg; none spawn
    kwarg
    
    +------------------------+-----------------+------------------------------+
    | Benchmark              | spawn_36_master | spawn_36_tuple2              |
    +========================+=================+==============================+
    | gevent spawn           | 13.2 us         | 11.9 us: 1.12x faster (-10%) |
    +------------------------+-----------------+------------------------------+
    | gevent sleep           | 1.71 us         | 1.90 us: 1.11x slower (+11%) |
    +------------------------+-----------------+------------------------------+
    | geventpool spawn       | 19.9 us         | 15.9 us: 1.25x faster (-20%) |
    +------------------------+-----------------+------------------------------+
    | geventpool sleep       | 3.54 us         | 3.75 us: 1.06x slower (+6%)  |
    +------------------------+-----------------+------------------------------+
    | geventpool spawn kwarg | 20.3 us         | 15.9 us: 1.27x faster (-22%) |
    +------------------------+-----------------+------------------------------+
    | geventraw spawn kwarg  | 5.80 us         | 6.10 us: 1.05x slower (+5%)  |
    +------------------------+-----------------+------------------------------+
    
    Not significant (9): eventlet spawn; eventlet sleep; geventraw spawn;
    geventraw sleep; none spawn; geventpool join; eventlet spawn kwarg;
    gevent spawn kwarg; none spawn kwarg
    
    +------------------+-------------------+------------------------------+
    | Benchmark        | spawn_pypy_master | spawn_pypy_tuple2            |
    +==================+===================+==============================+
    | eventlet spawn   | 30.5 us           | 28.9 us: 1.05x faster (-5%)  |
    +------------------+-------------------+------------------------------+
    | eventlet sleep   | 3.39 us           | 3.19 us: 1.06x faster (-6%)  |
    +------------------+-------------------+------------------------------+
    | gevent spawn     | 9.89 us           | 17.2 us: 1.73x slower (+73%) |
    +------------------+-------------------+------------------------------+
    | gevent sleep     | 3.14 us           | 3.99 us: 1.27x slower (+27%) |
    +------------------+-------------------+------------------------------+
    | geventpool spawn | 12.3 us           | 20.1 us: 1.63x slower (+63%) |
    +------------------+-------------------+------------------------------+
    
    Not significant (1): geventpool sleep
    
    +------------------------+---------------+-------------------------------+
    | Benchmark              | spawn_36_13a1 | spawn_36_tuple2               |
    +========================+===============+===============================+
    | eventlet spawn         | 14.0 us       | 13.2 us: 1.06x faster (-6%)   |
    +------------------------+---------------+-------------------------------+
    | gevent spawn           | 4.25 us       | 11.9 us: 2.79x slower (+179%) |
    +------------------------+---------------+-------------------------------+
    | gevent sleep           | 2.78 us       | 1.90 us: 1.46x faster (-32%)  |
    +------------------------+---------------+-------------------------------+
    | geventpool spawn       | 10.4 us       | 15.9 us: 1.52x slower (+52%)  |
    +------------------------+---------------+-------------------------------+
    | geventpool sleep       | 5.52 us       | 3.75 us: 1.47x faster (-32%)  |
    +------------------------+---------------+-------------------------------+
    | geventraw spawn        | 2.56 us       | 5.09 us: 1.99x slower (+99%)  |
    +------------------------+---------------+-------------------------------+
    | geventraw sleep        | 738 ns        | 838 ns: 1.14x slower (+14%)   |
    +------------------------+---------------+-------------------------------+
    | geventpool join        | 3.94 us       | 1.75 us: 2.25x faster (-56%)  |
    +------------------------+---------------+-------------------------------+
    | gevent spawn kwarg     | 5.50 us       | 12.1 us: 2.19x slower (+119%) |
    +------------------------+---------------+-------------------------------+
    | geventpool spawn kwarg | 11.3 us       | 15.9 us: 1.41x slower (+41%)  |
    +------------------------+---------------+-------------------------------+
    | geventraw spawn kwarg  | 3.90 us       | 6.10 us: 1.56x slower (+56%)  |
    +------------------------+---------------+-------------------------------+
    
    Not significant (4): eventlet sleep; none spawn; eventlet spawn kwarg; none spawn kwarg
    
    The eventlet, sleep, join and raw tests serve as controls, so we can see
    that there's up to ~10% variance between most runs anyway.
    
    CPython 3.6 shows the least variance so those 10-20% improvement
    numbers are probably fairly close.
    
    PyPy sadly gets *slower* with this change for reasons that are utterly
    unclear.
    
    Compared to 1.3a1 (last benchmark) we're still up to 2-3x slower.
    
    Creation of a raw greenlet shows 2.66us on CPython 3.6.4 vs the 3.65us
    I reported in #755.
    760a080c
greenlet.py 33.4 KB