diff options
author | Valentin Bartenev <vbart@nginx.com> | 2020-12-14 17:15:49 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2020-12-14 17:15:49 +0300 |
commit | 8d65a3303bde4fa2725310cd38af311e503e75ae (patch) | |
tree | 850bc98673a37ed802fd18488eceeca6fb85e83b /src/python | |
parent | 1e9def50c8ecc9f9331908b5fd46b218019a0fb0 (diff) | |
download | unit-8d65a3303bde4fa2725310cd38af311e503e75ae.tar.gz unit-8d65a3303bde4fa2725310cd38af311e503e75ae.tar.bz2 |
Python: WSGI environment copying moved out of request processing.
The WSGI environment dictionary contains a number of static items, that are
pre-initialized on application start. Then it's copied for each request to be
filled with request-related data.
Now this dictionary copy operation will be done between processing of requests,
which should save some CPU cycles during request processing and thus reduce
response latency for non-peak load periods.
Diffstat (limited to 'src/python')
-rw-r--r-- | src/python/nxt_python_wsgi.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c index da7b183c..77c45af5 100644 --- a/src/python/nxt_python_wsgi.c +++ b/src/python/nxt_python_wsgi.c @@ -59,6 +59,7 @@ static void nxt_python_wsgi_done(void); static void nxt_python_request_handler(nxt_unit_request_info_t *req); static PyObject *nxt_python_create_environ(nxt_python_app_conf_t *c); +static PyObject *nxt_python_copy_environ(nxt_unit_request_info_t *req); static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx); static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, nxt_unit_sptr_t *sptr, uint32_t size); @@ -221,6 +222,7 @@ nxt_python_wsgi_ctx_data_alloc(void **pdata) } pctx->write = NULL; + pctx->environ = NULL; pctx->start_resp = PyCFunction_New(nxt_py_start_resp_method, (PyObject *) pctx); @@ -237,6 +239,11 @@ nxt_python_wsgi_ctx_data_alloc(void **pdata) goto fail; } + pctx->environ = nxt_python_copy_environ(NULL); + if (nxt_slow_path(pctx->environ == NULL)) { + goto fail; + } + *pdata = pctx; return NXT_UNIT_OK; @@ -258,6 +265,7 @@ nxt_python_wsgi_ctx_data_free(void *data) Py_XDECREF(pctx->start_resp); Py_XDECREF(pctx->write); + Py_XDECREF(pctx->environ); Py_XDECREF(pctx); } @@ -295,6 +303,7 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) int rc; PyObject *environ, *args, *response, *iterator, *item; PyObject *close, *result; + nxt_bool_t prepare_environ; nxt_python_ctx_t *pctx; pctx = req->ctx->data; @@ -305,6 +314,19 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) PyEval_RestoreThread(pctx->thread_state); + if (nxt_slow_path(pctx->environ == NULL)) { + pctx->environ = nxt_python_copy_environ(req); + + if (pctx->environ == NULL) { + prepare_environ = 0; + + rc = NXT_UNIT_ERROR; + goto done; + } + } + + prepare_environ = 1; + environ = nxt_python_get_environ(pctx); if (nxt_slow_path(environ == NULL)) { rc = NXT_UNIT_ERROR; @@ -418,6 +440,14 @@ done: pctx->req = NULL; nxt_unit_request_done(req, rc); + + if (nxt_fast_path(prepare_environ)) { + PyEval_RestoreThread(pctx->thread_state); + + pctx->environ = nxt_python_copy_environ(NULL); + + pctx->thread_state = PyEval_SaveThread(); + } } @@ -532,23 +562,30 @@ fail: static PyObject * -nxt_python_get_environ(nxt_python_ctx_t *pctx) +nxt_python_copy_environ(nxt_unit_request_info_t *req) { - int rc; - uint32_t i, j, vl; - PyObject *environ; - nxt_unit_field_t *f, *f2; - nxt_unit_request_t *r; + PyObject *environ; environ = PyDict_Copy(nxt_py_environ_ptyp); + if (nxt_slow_path(environ == NULL)) { - nxt_unit_req_error(pctx->req, + nxt_unit_req_alert(req, "Python failed to copy the \"environ\" dictionary"); - - return NULL; + nxt_python_print_exception(); } - pctx->environ = environ; + return environ; +} + + +static PyObject * +nxt_python_get_environ(nxt_python_ctx_t *pctx) +{ + int rc; + uint32_t i, j, vl; + PyObject *environ; + nxt_unit_field_t *f, *f2; + nxt_unit_request_t *r; r = pctx->req->request; @@ -628,7 +665,7 @@ nxt_python_get_environ(nxt_python_ctx_t *pctx) #undef RC - if (nxt_slow_path(PyDict_SetItem(environ, nxt_py_wsgi_input_str, + if (nxt_slow_path(PyDict_SetItem(pctx->environ, nxt_py_wsgi_input_str, (PyObject *) pctx) != 0)) { nxt_unit_req_error(pctx->req, @@ -636,11 +673,15 @@ nxt_python_get_environ(nxt_python_ctx_t *pctx) goto fail; } + environ = pctx->environ; + pctx->environ = NULL; + return environ; fail: - Py_DECREF(environ); + Py_DECREF(pctx->environ); + pctx->environ = NULL; return NULL; } |