bpo-40137: Move state lookups out of the critical path (GH-25492)

This commit is contained in:
Raymond Hettinger 2021-04-21 15:22:22 -07:00 committed by GitHub
parent 760da626ff
commit 139c232f38
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -12,18 +12,6 @@
All rights reserved.
*/
/* partial object **********************************************************/
typedef struct {
PyObject_HEAD
PyObject *fn;
PyObject *args;
PyObject *kw;
PyObject *dict; /* __dict__ */
PyObject *weakreflist; /* List of weak references */
vectorcallfunc vectorcall;
} partialobject;
typedef struct _functools_state {
/* this object is used delimit args and keywords in the cache keys */
PyObject *kwd_mark;
@ -40,6 +28,19 @@ get_functools_state(PyObject *module)
return (_functools_state *)state;
}
/* partial object **********************************************************/
typedef struct {
PyObject_HEAD
PyObject *fn;
PyObject *args;
PyObject *kw;
PyObject *dict; /* __dict__ */
PyObject *weakreflist; /* List of weak references */
vectorcallfunc vectorcall;
} partialobject;
static void partial_setvectorcall(partialobject *pto);
static struct PyModuleDef _functools_module;
static PyObject *
@ -781,13 +782,16 @@ typedef struct lru_cache_object {
PyObject *func;
Py_ssize_t maxsize;
Py_ssize_t misses;
/* the kwd_mark is used delimit args and keywords in the cache keys */
PyObject *kwd_mark;
PyTypeObject *lru_list_elem_type;
PyObject *cache_info_type;
PyObject *dict;
PyObject *weakreflist;
} lru_cache_object;
static PyObject *
lru_cache_make_key(_functools_state *state, PyObject *args,
lru_cache_make_key(PyObject *kwd_mark, PyObject *args,
PyObject *kwds, int typed)
{
PyObject *key, *keyword, *value;
@ -827,8 +831,8 @@ lru_cache_make_key(_functools_state *state, PyObject *args,
PyTuple_SET_ITEM(key, key_pos++, item);
}
if (kwds_size) {
Py_INCREF(state->kwd_mark);
PyTuple_SET_ITEM(key, key_pos++, state->kwd_mark);
Py_INCREF(kwd_mark);
PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
Py_INCREF(keyword);
PyTuple_SET_ITEM(key, key_pos++, keyword);
@ -872,12 +876,7 @@ infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwd
{
PyObject *result;
Py_hash_t hash;
_functools_state *state;
state = get_functools_state_by_type(Py_TYPE(self));
if (state == NULL) {
return NULL;
}
PyObject *key = lru_cache_make_key(state, args, kwds, self->typed);
PyObject *key = lru_cache_make_key(self->kwd_mark, args, kwds, self->typed);
if (!key)
return NULL;
hash = PyObject_Hash(key);
@ -977,13 +976,8 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
lru_list_elem *link;
PyObject *key, *result, *testresult;
Py_hash_t hash;
_functools_state *state;
state = get_functools_state_by_type(Py_TYPE(self));
if (state == NULL) {
return NULL;
}
key = lru_cache_make_key(state, args, kwds, self->typed);
key = lru_cache_make_key(self->kwd_mark, args, kwds, self->typed);
if (!key)
return NULL;
hash = PyObject_Hash(key);
@ -1038,7 +1032,7 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
{
/* Cache is not full, so put the result in a new link */
link = (lru_list_elem *)PyObject_New(lru_list_elem,
state->lru_list_elem_type);
self->lru_list_elem_type);
if (link == NULL) {
Py_DECREF(key);
Py_DECREF(result);
@ -1149,6 +1143,7 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
lru_cache_object *obj;
Py_ssize_t maxsize;
PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
_functools_state *state;
static char *keywords[] = {"user_function", "maxsize", "typed",
"cache_info_type", NULL};
@ -1164,6 +1159,11 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
return NULL;
}
state = get_functools_state_by_type(type);
if (state == NULL) {
return NULL;
}
/* select the caching function, and make/inc maxsize_O */
if (maxsize_O == Py_None) {
wrapper = infinite_lru_cache_wrapper;
@ -1203,6 +1203,10 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
obj->func = func;
obj->misses = obj->hits = 0;
obj->maxsize = maxsize;
Py_INCREF(state->kwd_mark);
obj->kwd_mark = state->kwd_mark;
Py_INCREF(state->lru_list_elem_type);
obj->lru_list_elem_type = state->lru_list_elem_type;
Py_INCREF(cache_info_type);
obj->cache_info_type = cache_info_type;
obj->dict = NULL;
@ -1238,6 +1242,8 @@ lru_cache_tp_clear(lru_cache_object *self)
lru_list_elem *list = lru_cache_unlink_list(self);
Py_CLEAR(self->func);
Py_CLEAR(self->cache);
Py_CLEAR(self->kwd_mark);
Py_CLEAR(self->lru_list_elem_type);
Py_CLEAR(self->cache_info_type);
Py_CLEAR(self->dict);
lru_cache_clear_list(list);
@ -1330,6 +1336,8 @@ lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
}
Py_VISIT(self->func);
Py_VISIT(self->cache);
Py_VISIT(self->kwd_mark);
Py_VISIT(self->lru_list_elem_type);
Py_VISIT(self->cache_info_type);
Py_VISIT(self->dict);
return 0;