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

Use PEP 669 API for cprofile #103533

Closed
gaogaotiantian opened this issue Apr 14, 2023 · 0 comments
Closed

Use PEP 669 API for cprofile #103533

gaogaotiantian opened this issue Apr 14, 2023 · 0 comments
Labels
performance Performance or resource usage stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@gaogaotiantian
Copy link
Member

gaogaotiantian commented Apr 14, 2023

Feature or enhancement

Replace the current setprofile mechanism with PEP 669 API for cProfile.

Pitch

It's faster.

Before:

Hanoi: 0.342869599997357, 1.4579414000036195, 4.252174587699983
fib: 0.15549560000363272, 0.7588815999988583, 4.88040561907301

Hanoi: 0.33156009999947855, 1.394542599999113, 4.2060024713507635
fib: 0.16397210000286577, 0.7469802000050549, 4.555532313070332

Hanoi: 0.3341937000004691, 1.394005099995411, 4.171248889471747
fib: 0.15704140000161715, 0.7399598000047263, 4.711877250184387

Hanoi: 0.33133889999589883, 1.3821628000005148, 4.171447421409387
fib: 0.15387790000386303, 0.754370700000436, 4.902397940064804

Hanoi: 0.3403002000050037, 1.3969628000049852, 4.105089564991276
fib: 0.15468130000226665, 0.761441399998148, 4.922646758121312

After:

Hanoi: 0.3318088000014541, 1.2147841000041808, 3.661096691826309
fib: 0.15522490000148537, 0.6360437999974238, 4.097562955372092

Hanoi: 0.33085879999998724, 1.1502422000048682, 3.476535005279934
fib: 0.15410060000431258, 0.6056611999956658, 3.9302974808580635

Hanoi: 0.35002540000277804, 1.145935599997756, 3.273864125256799
fib: 0.1540030999967712, 0.5974198000039905, 3.8792712615299036

Hanoi: 0.3338971999983187, 1.1459307999975863, 3.431986851052829
fib: 0.16891020000184653, 0.6197690999979386, 3.6692224625343126

Hanoi: 0.3318254999976489, 1.1875411000000895, 3.578812056362467
fib: 0.1544136999946204, 0.5971600999982911, 3.867274082669449

20%+ speed up for overhead.

I guess the incentive is not in doubt, but I did have some issues when I implemented it.

  1. There is a very slight backward compatibility issue, or it's more like a design decision. The profiler has to disable its own profiling now.
# This works on main, but I don't think that's intuitive.
pr = cProfile.Profile()
pr.enable()
pr = cProfile.Profile()
pr.disable()

We can make it work as before, I just think this is not the right way to do it with PEP 669. Because of this, I changed an old (15 years) test in test_cprofile.

  1. We need to get the actual c function from the descriptor, for which I used the code in the current legacy tracing. However, _PyInstrumentation_MISSING is not exposed so I had to store it locally (keep reading it from sys is a bit expensive).

  2. On that matter, are we going to expose some APIs on C? It would be nice if I don't have to get sys.monitoring and do stuff from there. We have some defined constants but some APIs could be handy. We may be able to reduce the overhead a bit if we have an interface like PyEval_SetProfile.

Addendum:

Benchmark Code
import timeit

hanoi_setup = """
import cProfile
def test():
    def TowerOfHanoi(n, source, destination, auxiliary):
        if n == 1:
            return
        TowerOfHanoi(n - 1, source, auxiliary, destination)
        TowerOfHanoi(n - 1, auxiliary, destination, source)
    TowerOfHanoi(16, "A", "B", "C")
pr = cProfile.Profile()
"""

fib_setup = """
import cProfile
def test():
    def fib(n):
        if n <= 1:
            return 1
        return fib(n - 1) + fib(n - 2)
    fib(21)
pr = cProfile.Profile()
"""

test_baseline = """
test()
"""

test_profile = """
pr.enable()
test()
pr.disable()
"""

baseline = timeit.timeit(test_baseline, setup=hanoi_setup, number=100)
profile = timeit.timeit(test_profile, setup=hanoi_setup, number=100)
print(f"Hanoi: {baseline}, {profile}, {profile / baseline}")

baseline = timeit.timeit(test_baseline, setup=fib_setup, number=100)
profile = timeit.timeit(test_profile, setup=fib_setup, number=100)
print(f"fib: {baseline}, {profile}, {profile / baseline}")

Linked PRs

@gaogaotiantian gaogaotiantian added the type-feature A feature request or enhancement label Apr 14, 2023
@arhadthedev arhadthedev added stdlib Python modules in the Lib dir performance Performance or resource usage labels Apr 14, 2023
carljm added a commit to carljm/cpython that referenced this issue May 5, 2023
* main:
  pythongh-99113: Add PyInterpreterConfig.own_gil (pythongh-104204)
  pythongh-104146: Remove unused var 'parser_body_declarations' from clinic.py (python#104214)
  pythongh-99113: Add Py_MOD_PER_INTERPRETER_GIL_SUPPORTED (pythongh-104205)
  pythongh-104108: Add the Py_mod_multiple_interpreters Module Def Slot (pythongh-104148)
  pythongh-99113: Share the GIL via PyInterpreterState.ceval.gil (pythongh-104203)
  pythonGH-100479: Add `pathlib.PurePath.with_segments()` (pythonGH-103975)
  pythongh-69152: Add _proxy_response_headers attribute to HTTPConnection (python#26152)
  pythongh-103533: Use PEP 669 APIs for cprofile (pythonGH-103534)
  pythonGH-96803: Add three C-API functions to make _PyInterpreterFrame less opaque for users of PEP 523. (pythonGH-96849)
jbower-fb pushed a commit to jbower-fb/cpython-jbowerfb that referenced this issue May 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Performance or resource usage stdlib Python modules in the Lib dir type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

2 participants