diff options
author | Yurii Karabas <1998uriyyo@gmail.com> | 2020-11-25 10:43:18 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-25 10:43:18 (GMT) |
commit | 7301979b23406220510dd2c7934a21b41b647119 (patch) | |
tree | 296b337317ac71d34001c17f4b4b7bea918cbf6f /Python/compile.c | |
parent | 85c84920f511d0d73a133336daeaf715a022cd64 (diff) | |
download | cpython-7301979b23406220510dd2c7934a21b41b647119.zip cpython-7301979b23406220510dd2c7934a21b41b647119.tar.gz cpython-7301979b23406220510dd2c7934a21b41b647119.tar.bz2 |
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>
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 70 |
1 files changed, 27 insertions, 43 deletions
diff --git a/Python/compile.c b/Python/compile.c index 1989b4a..57aa434 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -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 |