mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
bpo-42202: Store func annotations as a tuple (GH-23316)
Reduce memory footprint and improve performance of loading modules having many func annotations. >>> sys.getsizeof({"a":"int","b":"int","return":"int"}) 232 >>> sys.getsizeof(("a","int","b","int","return","int")) 88 The tuple is converted into dict on the fly when `func.__annotations__` is accessed first. Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-authored-by: Inada Naoki <songofacandy@gmail.com>
This commit is contained in:
parent
85c84920f5
commit
7301979b23
8 changed files with 174 additions and 155 deletions
|
@ -2027,26 +2027,24 @@ compiler_visit_annexpr(struct compiler *c, expr_ty annotation)
|
|||
|
||||
static int
|
||||
compiler_visit_argannotation(struct compiler *c, identifier id,
|
||||
expr_ty annotation, PyObject *names)
|
||||
expr_ty annotation, Py_ssize_t *annotations_len)
|
||||
{
|
||||
if (annotation) {
|
||||
PyObject *mangled;
|
||||
VISIT(c, annexpr, annotation);
|
||||
mangled = _Py_Mangle(c->u->u_private, id);
|
||||
PyObject *mangled = _Py_Mangle(c->u->u_private, id);
|
||||
if (!mangled)
|
||||
return 0;
|
||||
if (PyList_Append(names, mangled) < 0) {
|
||||
Py_DECREF(mangled);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ADDOP_LOAD_CONST(c, mangled);
|
||||
Py_DECREF(mangled);
|
||||
VISIT(c, annexpr, annotation);
|
||||
*annotations_len += 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_visit_argannotations(struct compiler *c, asdl_arg_seq* args,
|
||||
PyObject *names)
|
||||
Py_ssize_t *annotations_len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < asdl_seq_LEN(args); i++) {
|
||||
|
@ -2055,7 +2053,7 @@ compiler_visit_argannotations(struct compiler *c, asdl_arg_seq* args,
|
|||
c,
|
||||
arg->arg,
|
||||
arg->annotation,
|
||||
names))
|
||||
annotations_len))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
@ -2065,58 +2063,44 @@ static int
|
|||
compiler_visit_annotations(struct compiler *c, arguments_ty args,
|
||||
expr_ty returns)
|
||||
{
|
||||
/* Push arg annotation dict.
|
||||
/* Push arg annotation names and values.
|
||||
The expressions are evaluated out-of-order wrt the source code.
|
||||
|
||||
Return 0 on error, -1 if no dict pushed, 1 if a dict is pushed.
|
||||
Return 0 on error, -1 if no annotations pushed, 1 if a annotations is pushed.
|
||||
*/
|
||||
static identifier return_str;
|
||||
PyObject *names;
|
||||
Py_ssize_t len;
|
||||
names = PyList_New(0);
|
||||
if (!names)
|
||||
return 0;
|
||||
Py_ssize_t annotations_len = 0;
|
||||
|
||||
if (!compiler_visit_argannotations(c, args->args, names))
|
||||
goto error;
|
||||
if (!compiler_visit_argannotations(c, args->posonlyargs, names))
|
||||
goto error;
|
||||
if (!compiler_visit_argannotations(c, args->args, &annotations_len))
|
||||
return 0;
|
||||
if (!compiler_visit_argannotations(c, args->posonlyargs, &annotations_len))
|
||||
return 0;
|
||||
if (args->vararg && args->vararg->annotation &&
|
||||
!compiler_visit_argannotation(c, args->vararg->arg,
|
||||
args->vararg->annotation, names))
|
||||
goto error;
|
||||
if (!compiler_visit_argannotations(c, args->kwonlyargs, names))
|
||||
goto error;
|
||||
args->vararg->annotation, &annotations_len))
|
||||
return 0;
|
||||
if (!compiler_visit_argannotations(c, args->kwonlyargs, &annotations_len))
|
||||
return 0;
|
||||
if (args->kwarg && args->kwarg->annotation &&
|
||||
!compiler_visit_argannotation(c, args->kwarg->arg,
|
||||
args->kwarg->annotation, names))
|
||||
goto error;
|
||||
args->kwarg->annotation, &annotations_len))
|
||||
return 0;
|
||||
|
||||
if (!return_str) {
|
||||
return_str = PyUnicode_InternFromString("return");
|
||||
if (!return_str)
|
||||
goto error;
|
||||
return 0;
|
||||
}
|
||||
if (!compiler_visit_argannotation(c, return_str, returns, names)) {
|
||||
goto error;
|
||||
if (!compiler_visit_argannotation(c, return_str, returns, &annotations_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = PyList_GET_SIZE(names);
|
||||
if (len) {
|
||||
PyObject *keytuple = PyList_AsTuple(names);
|
||||
Py_DECREF(names);
|
||||
ADDOP_LOAD_CONST_NEW(c, keytuple);
|
||||
ADDOP_I(c, BUILD_CONST_KEY_MAP, len);
|
||||
if (annotations_len) {
|
||||
ADDOP_I(c, BUILD_TUPLE, annotations_len);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
Py_DECREF(names);
|
||||
return -1;
|
||||
}
|
||||
|
||||
error:
|
||||
Py_DECREF(names);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue