uvloop
uvloop copied to clipboard
Improve performance by using Python C API to enter/exit context
From perf, callstack before the change:
--54.22%--__pyx_f_6uvloop_4loop___uv_stream_on_read
|
--52.82%--__pyx_f_6uvloop_4loop_run_in_context1
|
--51.06%--cfunction_vectorcall_FASTCALL_KEYWORDS
context_run
|
--50.49%--_PyObject_VectorcallTstate.lto_priv.18
|
--50.28%--method_vectorcall
|
--49.45%--__pyx_pw_6picows_6picows_10WSProtocol_13data_received
After the change:
--51.71%--__pyx_f_6uvloop_4loop___uv_stream_on_read
|
--50.42%--__pyx_f_6uvloop_4loop_run_in_context1
|
--49.13%--__pyx_pw_6picows_6picows_10WSProtocol_13data_received
On a side note, I have removed Py_INCREF/Py_DECREF because cython does it itself when method is called directly.
static CYTHON_INLINE PyObject *__pyx_f_6uvloop_4loop_run_in_context(PyObject *__pyx_v_context, PyObject *__pyx_v_method) {
PyObject *__pyx_r = NULL;
__Pyx_RefNannyDeclarations
int __pyx_t_1;
PyObject *__pyx_t_2 = NULL;
PyObject *__pyx_t_3 = NULL;
PyObject *__pyx_t_4 = NULL;
unsigned int __pyx_t_5;
int __pyx_t_6;
char const *__pyx_t_7;
PyObject *__pyx_t_8 = NULL;
PyObject *__pyx_t_9 = NULL;
PyObject *__pyx_t_10 = NULL;
PyObject *__pyx_t_11 = NULL;
PyObject *__pyx_t_12 = NULL;
PyObject *__pyx_t_13 = NULL;
int __pyx_t_14;
int __pyx_lineno = 0;
const char *__pyx_filename = NULL;
int __pyx_clineno = 0;
__Pyx_RefNannySetupContext("run_in_context", 1);
/* "uvloop/loop.pyx":95
*
* cdef inline run_in_context(context, method):
* Context_Enter(context) # <<<<<<<<<<<<<<
* try:
* return method()
*/
__pyx_t_1 = Context_Enter(__pyx_v_context); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(0, 95, __pyx_L1_error)
/* "uvloop/loop.pyx":96
* cdef inline run_in_context(context, method):
* Context_Enter(context)
* try: # <<<<<<<<<<<<<<
* return method()
* finally:
*/
/*try:*/ {
/* "uvloop/loop.pyx":97
* Context_Enter(context)
* try:
* return method() # <<<<<<<<<<<<<<
* finally:
* Context_Exit(context)
*/
__Pyx_XDECREF(__pyx_r);
__Pyx_INCREF(__pyx_v_method);
__pyx_t_3 = __pyx_v_method; __pyx_t_4 = NULL;
__pyx_t_5 = 0;
#if CYTHON_UNPACK_METHODS
if (unlikely(PyMethod_Check(__pyx_t_3))) {
__pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
if (likely(__pyx_t_4)) {
PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
__Pyx_INCREF(__pyx_t_4);
__Pyx_INCREF(function);
__Pyx_DECREF_SET(__pyx_t_3, function);
__pyx_t_5 = 1;
}
}
#endif
{
PyObject *__pyx_callargs[2] = {__pyx_t_4, NULL};
__pyx_t_2 = __Pyx_PyObject_FastCall(__pyx_t_3, __pyx_callargs+1-__pyx_t_5, 0+__pyx_t_5);
__Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 97, __pyx_L4_error)
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
}
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
goto __pyx_L3_return;
}
/* "uvloop/loop.pyx":99
* return method()
* finally:
* Context_Exit(context) # <<<<<<<<<<<<<<
*
*
*/
/*finally:*/ {
__pyx_L4_error:;
/*exception exit:*/{
__Pyx_PyThreadState_declare
__Pyx_PyThreadState_assign
__pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0;
__Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
__Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_11, &__pyx_t_12, &__pyx_t_13);
if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10) < 0)) __Pyx_ErrFetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10);
__Pyx_XGOTREF(__pyx_t_8);
__Pyx_XGOTREF(__pyx_t_9);
__Pyx_XGOTREF(__pyx_t_10);
__Pyx_XGOTREF(__pyx_t_11);
__Pyx_XGOTREF(__pyx_t_12);
__Pyx_XGOTREF(__pyx_t_13);
__pyx_t_1 = __pyx_lineno; __pyx_t_6 = __pyx_clineno; __pyx_t_7 = __pyx_filename;
{
__pyx_t_14 = Context_Exit(__pyx_v_context); if (unlikely(__pyx_t_14 == ((int)-1))) __PYX_ERR(0, 99, __pyx_L7_error)
}
if (PY_MAJOR_VERSION >= 3) {
__Pyx_XGIVEREF(__pyx_t_11);
__Pyx_XGIVEREF(__pyx_t_12);
__Pyx_XGIVEREF(__pyx_t_13);
__Pyx_ExceptionReset(__pyx_t_11, __pyx_t_12, __pyx_t_13);
}
__Pyx_XGIVEREF(__pyx_t_8);
__Pyx_XGIVEREF(__pyx_t_9);
__Pyx_XGIVEREF(__pyx_t_10);
__Pyx_ErrRestore(__pyx_t_8, __pyx_t_9, __pyx_t_10);
__pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0;
__pyx_lineno = __pyx_t_1; __pyx_clineno = __pyx_t_6; __pyx_filename = __pyx_t_7;
goto __pyx_L1_error;
__pyx_L7_error:;
if (PY_MAJOR_VERSION >= 3) {
__Pyx_XGIVEREF(__pyx_t_11);
__Pyx_XGIVEREF(__pyx_t_12);
__Pyx_XGIVEREF(__pyx_t_13);
__Pyx_ExceptionReset(__pyx_t_11, __pyx_t_12, __pyx_t_13);
}
__Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
__Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
__Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
__pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0;
goto __pyx_L1_error;
}
__pyx_L3_return: {
__pyx_t_13 = __pyx_r;
__pyx_r = 0;
__pyx_t_6 = Context_Exit(__pyx_v_context); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(0, 99, __pyx_L1_error)
__pyx_r = __pyx_t_13;
__pyx_t_13 = 0;
goto __pyx_L0;
}
}