Skip to content
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

Lazily compute lineno of tracebacks for efficient exception handling #95238

Closed
kumaraditya303 opened this issue Jul 25, 2022 · 7 comments
Closed
Assignees
Labels
3.12 bugs and security fixes performance Performance or resource usage triaged The issue has been accepted as valid by a triager. type-feature A feature request or enhancement

Comments

@kumaraditya303
Copy link
Contributor

kumaraditya303 commented Jul 25, 2022

By lazily computing tb_lineno of tracebacks, we can avoid parsing the line and column table and avoid a lot of overhead that comes with accessing line number information.

See faster-cpython/ideas#407 for discussion.

@kumaraditya303
Copy link
Contributor Author

kumaraditya303 commented Jul 25, 2022

PR #95237 computes line number lazily.

This microbenchmark shows a 25% speedup when handling exception:

import pyperf
from pyperf import Runner


def bench(loops):
    x = object()
    t1 = pyperf.perf_counter()
    for i in range(loops):
        try:
            x.y
        except AttributeError:
            pass
    t2 = pyperf.perf_counter()
    return t2 - t1


runner = Runner()
runner.bench_time_func('bench exception handling', bench)

Benchmark results:

Benchmark main patch
bench exception handling 614 ns 491 ns: 1.25x faster

This is on Linux release build without PGO and LTO.

@erlend-aasland erlend-aasland added type-feature A feature request or enhancement triaged The issue has been accepted as valid by a triager. labels Jul 25, 2022
@kumaraditya303 kumaraditya303 changed the title Lazy traceback for efficient exception handling Lazily compute llineno of tracebacks for efficient exception handling Jul 25, 2022
@kumaraditya303 kumaraditya303 self-assigned this Jul 25, 2022
@kumaraditya303 kumaraditya303 changed the title Lazily compute llineno of tracebacks for efficient exception handling Lazily compute lineno of tracebacks for efficient exception handling Jul 25, 2022
@kumaraditya303 kumaraditya303 added the 3.12 bugs and security fixes label Jul 25, 2022
@kumaraditya303
Copy link
Contributor Author

PR #95237 makes tb_lineno of PyTracebackObject lazy. C extension modules must call PyTraceback_GetLineNumber to get the line number.

@scoder @da-woods Can you confirm if Cython will be affected by this change? Thanks!

See also discourse discussion

@da-woods
Copy link
Contributor

I did a quick search of Cython and couldn't find any use of tb_lineno so I don't think it's a problem. Even if it was, 3.12 is a while off so there would be plenty of time to find a solution.

@gpshead
Copy link
Member

gpshead commented Aug 25, 2022

Results from a pyperformance run would be more informative than the microbenchmark when it comes to deciding about the deprecation timeline exemption asked for in python/steering-council#136.

@kumaraditya303
Copy link
Contributor Author

Another benchmark speedup by 50% on Linux gcc with PGO build:
Benchmark:

import pyperf
from pyperf import Runner


def bench(loops):
    x = {1: "foo", 2: "baz"}
    t1 = pyperf.perf_counter()
    for _ in range(loops):
        try:
            x["fooz"]
        except KeyError:
            pass
    t2 = pyperf.perf_counter()
    return t2 - t1


runner = Runner()
runner.bench_time_func('bench exception handling', bench)

Results

Benchmark base patch
bench exception handling 297 ns 196 ns: 1.51x faster

@kumaraditya303
Copy link
Contributor Author

Results from a pyperformance run would be more informative than the microbenchmark when it comes to deciding about the deprecation timeline exemption asked for in python/steering-council#136.

pyperformance has no benchmarks which use exception handling in hot paths. The speedup if any would be dominated by the noise in the benchmark itself. Also moving pyperformance needle by even 1% isn't easy, the accumulation of these kinds of targeted improvements will result in 1% or more but just one change isn't going to do it.

@kumaraditya303
Copy link
Contributor Author

Will be implemented as part of #96709

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes performance Performance or resource usage triaged The issue has been accepted as valid by a triager. type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

4 participants