-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
gh-92810: Reduce memory usage by ABCMeta.__subclasscheck__ #131914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
3 similar comments
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
Signed-off-by: Martynov Maxim <martinov_m_s_@mail.ru>
Signed-off-by: Martynov Maxim <martinov_m_s_@mail.ru>
Signed-off-by: Martynov Maxim <martinov_m_s_@mail.ru>
Signed-off-by: Martynov Maxim <martinov_m_s_@mail.ru>
Signed-off-by: Martynov Maxim <martinov_m_s_@mail.ru>
abf4bfe to
b7603e0
Compare
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
This comment was marked as outdated.
This comment was marked as outdated.
|
pyperformance results doesn't show a much difference: sudo ./venv/bin/python -m pyperf system tune
./venv/bin/python -m pyperformance run --rigorous --affinity 0,1,2,3,4,5main_cd4d0ae75c_rigorous_affinity.json DetailsBenchmarks with tag 'apps':
Benchmark hidden because not significant (1): html5lib Benchmarks with tag 'asyncio':
Benchmark hidden because not significant (13): async_tree_eager_tg, asyncio_tcp, async_tree_cpu_io_mixed, async_tree_none, async_tree_eager_io_tg, async_tree_memoization, async_tree_eager, asyncio_websockets, asyncio_tcp_ssl, async_tree_eager_io, coroutines, async_tree_io, async_tree_eager_memoization_tg Benchmarks with tag 'math':
Benchmark hidden because not significant (1): float Benchmarks with tag 'regex':
Benchmarks with tag 'serialize':
Benchmark hidden because not significant (4): xml_etree_iterparse, unpickle_list, unpickle_pure_python, pickle Benchmarks with tag 'startup':
Benchmarks with tag 'template':
Benchmark hidden because not significant (1): mako All benchmarks:
Benchmark hidden because not significant (38): xml_etree_iterparse, unpickle_list, bench_mp_pool, subparsers, sqlglot_v2_transpile, sqlalchemy_declarative, async_tree_eager_tg, many_optionals, unpickle_pure_python, deltablue, meteor_contest, sqlalchemy_imperative, html5lib, asyncio_tcp, bench_thread_pool, async_tree_cpu_io_mixed, async_tree_none, async_tree_eager_io_tg, telco, generators, sqlglot_v2_parse, async_tree_memoization, scimark_sor, pickle, gc_traversal, async_tree_eager, asyncio_websockets, sqlite_synth, asyncio_tcp_ssl, float, deepcopy, deepcopy_reduce, mako, logging_silent, async_tree_eager_io, coroutines, async_tree_io, async_tree_eager_memoization_tg |
|
I've updated microbenchmark script and results in the PR description: #131914 (comment). Previous microbenchmark implementation created global large class tree, and tested different According to these results, and to pyperformance run on my machine, timing is not that different comparing to |
|
Alternative implementation which eliminates |
|
I've seen your work but I really don't have enough time to estimate the impact for all cases. It's not that it's a bad change but
|
|
Thanks @picnixz, I understand your point. There is no rush here, the change can be landed any time. |
_abc._abc_subclasscheckhas very poor performance and (I think) a memory leak #92810For python build using
--enable-optimizations:benchmark.py
isinstance(child, Parent)2MiB...15MiB
3MiB...15MiB
10MiB...24MiB
10MiB...24MiB
issubclass(Child, Parent)0MiB...1MiB
0MiB...1MiB
6MiB...8MiB
5MiB...8MiB
isinstance(child, Grandparent)0MiB...2MiB
0MiB...1MiB
4MiB...7MiB
4MiB...7MiB
issubclass(Child, Grandparent)0MiB
0MiB
1MiB...2MiB
0MiB...1MiB
not isinstance(child, Sibling)1MiB...14MiB
1MiB...14MiB
14MiB...24MiB
13MiB...22MiB
not issubclass(Child, Sibling)0MiB
0MiB...1MiB
9MiB...11MiB
8MiB...11MiB
not isinstance(child, Cousin)0MiB
1MiB...2MiB
8MiB...10MiB
7MiB...9MiB
not issubclass(Child, Cousin)0MiB
0MiB...1MiB
5MiB...6MiB
3MiB...4MiB
not isinstance(child, Uncle)5706MiB...6331MiB
0MiB...1MiB
3796MiB...4423MiB
6MiB
not issubclass(Child, Uncle)5704MiB
0MiB
3794MiB...3795MiB
4MiB
Memory increment is measured during
isinstance()/issubclass()calls, not during preparation, like class creation or registration where actual registry allocation is performed. So memory usage in tables below is almost always 0.Timing drop for 2 first rows is mostly due to
cls._abc_cache.add(scls)call withindef register(slc, scls)which wasn't implemented before.isinstance(child, Parent.register)0MiB
0MiB
0MiB
0MiB
issubclass(Child, Parent.register)0MiB
0MiB
0MiB
0MiB
isinstance(child, Grandparent.register)0MiB
0MiB
0MiB
0MiB
issubclass(Child, Grandparent.register)0MiB
0MiB
0MiB
0MiB
not isinstance(child, Sibling.register)0MiB
1MiB
0MiB
2MiB
not issubclass(Child, Sibling.register)0MiB
1MiB
0MiB
2MiB
not isinstance(child, Cousin.register)0MiB
2MiB
0MiB
3MiB
not issubclass(Child, Cousin.register)0MiB
2MiB
0MiB
3MiB
not isinstance(child, Uncle.register)0MiB
2MiB...3MiB
0MiB
4MiB
not issubclass(Child, Uncle.register)0MiB
2MiB
0MiB
4MiB
This became a bit slower due to new checks, but this is rare case.
isinstance(child, Parent.__subclasses__)0MiB
0MiB
0MiB
0MiB
issubclass(Child, Parent.__subclasses__)0MiB
0MiB
0MiB
0MiB
isinstance(child, Grandparent.__subclasses__)0MiB
0MiB
0MiB
0MiB
issubclass(Child, Grandparent.__subclasses__)0MiB
0MiB
0MiB
0MiB
not isinstance(child, Sibling.__subclasses__)0MiB
0MiB
0MiB
1MiB
not issubclass(Child, Sibling.__subclasses__)0MiB
0MiB
0MiB
1MiB
not isinstance(child, Cousin.__subclasses__)0MiB
0MiB
0MiB
1MiB
not issubclass(Child, Cousin.__subclasses__)0MiB
0MiB
0MiB
1MiB
not isinstance(child, Uncle.__subclasses__)0MiB
1MiB
0MiB
2MiB
not issubclass(Child, Uncle.__subclasses__)0MiB
0MiB
0MiB
2MiB
Flamegraphs for
_py_abcimpl and testissubclass_uncle(the most time and memory consuming case onmain):main_vs_pr131914.tar.gz