Skip to content

gh-96143: Allow Linux perf profiler to see Python calls - #96123

Merged
miss-islington merged 50 commits into
python:mainfrom
pablogsal:perf
Aug 30, 2022
Merged

gh-96143: Allow Linux perf profiler to see Python calls#96123
miss-islington merged 50 commits into
python:mainfrom
pablogsal:perf

Conversation

@pablogsal

@pablogsalpablogsal commented Aug 19, 2022

Copy link
Copy Markdown
Member

Automerge-Triggered-By: GH:pablogsal

Comment threadObjects/codeobject.c Outdated
Comment threadPython/ceval.c Outdated

@markshannonmarkshannon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea if that assembly code does what you say, but I've reviewed the rest.

Definitely an intriguing idea.

Comment threadInclude/cpython/code.h Outdated
Comment threadInclude/internal/pycore_ceval.h Outdated
Comment threadObjects/codeobject.c Outdated
Comment threadObjects/codeobject.c Outdated
Comment threadObjects/codeobject.c Outdated
Comment threadObjects/codeobject.c Outdated
Comment threadObjects/codeobject.c Outdated
Comment threadPython/ceval.c Outdated
@pablogsal
pablogsalforce-pushed the perf branch 2 times, most recently from 9b009f2 to 439ef28CompareAugust 19, 2022 16:51
@tiran

Copy link
Copy Markdown
Member

You can use preprocesor macros if you name the file Objects/asm_trampoline.S or .sx instead of Objects/asm_trampoline.s. The .sx form needs a makefile rule.

@pablogsal

Copy link
Copy Markdown
MemberAuthor

You can use preprocesor macros if you name the file Objects/asm_trampoline.S or .sx instead of Objects/asm_trampoline.s. The .sx form needs a makefile rule.

Hummm, not sure I follow, could you maybe show me an example of what we can achieve with this?

@tiran

Copy link
Copy Markdown
Member

You can have multiple implementations in the same file:

 .text
.globl	_Py_trampoline_func_start
_Py_trampoline_func_start:
#ifdef __x86_64__
push %rbp
mov %rsp,%rbp
mov %rdi,%rax
mov %rsi,%rdi
mov %rdx,%rsi
mov %ecx,%edx
call *%rax
pop %rbp
ret
#endif // __x86_64__
#ifdef __aarch64__
TODO
#endif
.globl	_Py_trampoline_func_end
_Py_trampoline_func_end:

Comment threadInclude/internal/pycore_ceval.h Outdated
@gpsheadgpshead added type-feature A feature request or enhancement interpreter-core (Objects, Python, Grammar, and Parser dirs) labels Aug 20, 2022
@pablogsal
pablogsal marked this pull request as ready for review August 20, 2022 17:10
@pablogsal
pablogsal requested a review from a team as a code ownerAugust 20, 2022 17:10
@pablogsal
pablogsalforce-pushed the perf branch 3 times, most recently from df2a40d to dda9e04CompareAugust 20, 2022 17:26
@pablogsalpablogsal changed the title Allow Linux perf profiler to see Python callsgh-96143: Allow Linux perf profiler to see Python callsAug 20, 2022
@pablogsal
pablogsalforce-pushed the perf branch 3 times, most recently from f38dfc2 to 22fc892CompareAugust 20, 2022 17:46
Comment threadPCbuild/_freeze_module.vcxproj.filters Outdated
@pablogsal
pablogsalforce-pushed the perf branch 2 times, most recently from a2f4182 to 1b35ed3CompareAugust 20, 2022 18:31
@tiran

Copy link
Copy Markdown
Member

Why did you add a Windows build file? How about we do not define _PyPerfTrampoline_Init unless HAVE_PERF_TRAMPOLINE is defined?

@pablogsal

Copy link
Copy Markdown
MemberAuthor

Why did you add a Windows build file? How about we do not define _PyPerfTrampoline_Init unless HAVE_PERF_TRAMPOLINE is defined?

Then we need to add more ifdef every place is used but that works as well for sure

Comment threadObjects/perf_trampoline.c Outdated
Comment threadObjects/perf_trampoline.c Outdated
Comment threadObjects/perf_trampoline.c Outdated
Comment threadPython/sysmodule.c Outdated
Comment threadObjects/asm_trampoline.S
they now match the current code.

@gpsheadgpshead left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two thoughts have been running around in my mind:

(1) We've got the command line flag and sys API, but what about just enabling this system wide or at least task/job wide within a container? An environment variable that turns it on would make that easy without plumbing options through. PYTHONPERFSUPPORT=1 as another equivalent to -Xperf? That's usually done in initconfig.c alongside the -X processing I believe.

Second: multiprocessing spawn start method. If the -Xperf flag was passed to the parent process I assume the "spawn" method should also pass that to its children.

@pablogsal

pablogsal commented Aug 29, 2022

Copy link
Copy Markdown
MemberAuthor

Two thoughts have been running around in my mind:

(1) We've got the command line flag and sys API, but what about just enabling this system wide or at least task/job wide within a container? An environment variable that turns it on would make that easy without plumbing options through. PYTHONPERFSUPPORT=1 as another equivalent to -Xperf? That's usually done in initconfig.c alongside the -X processing I believe.

Second: multiprocessing spawn start method. If the -Xperf flag was passed to the parent process I assume the "spawn" method should also pass that to its children.

I think (1) makes sense and is indeed coherent with how we handle some of the other options like tracemalloc so I will add an environment variable alongside the -X option.

Regarding (2) I am not that sure. We don't do this for the rest of the flags that we pass around and you can achieve the same with the environment variable if you want. In any case, as that would require some tests I would prefer to do that in a separate PR as this is already gigantic

@pablogsal

pablogsal commented Aug 29, 2022

Copy link
Copy Markdown
MemberAuthor

I implemented the environment variable and solved a bunch of conflicts. Please check it out when you have time.

I also had to solve a bunch of conflicts. @gpshead if you are ok with the current status I would like us to land if everything looks good as the size of the PR is already attracting a bunch of merge conflicts in the build system, clinic and other files.

@pablogsal

Copy link
Copy Markdown
MemberAuthor

Ah wait, I need to document the environment variable. Will push a commit for that soon.

@pablogsal

Copy link
Copy Markdown
MemberAuthor

Ah wait, I need to document the environment variable. Will push a commit for that soon.

Done 👍

@pablogsal

Copy link
Copy Markdown
MemberAuthor

@erlend-aasland has mentioned that he was a bunch of docs improvements that he will do in a separate PR.

@pablogsal
pablogsal requested a review from gpsheadAugust 29, 2022 21:09

@gpsheadgpshead left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My comments are easy to address things that don't need further review - minor edits or added note/todo comments to our future selves.

Agreed that the docs can use some polishing up but all the important bits are there to seed that future work, thanks for writing them!

Thanks for taking on adding this feature! I expect we'll see how a backport fares internally.

Comment threadDoc/howto/perf_profiling.rst
Comment threadDoc/using/cmdline.rst
Comment threadLib/test/test_perf_profiler.py
Comment threadLib/test/test_perf_profiler.py
Comment threadObjects/perf_trampoline.c
Comment threadObjects/perf_trampoline.c
Comment threadObjects/perf_trampoline.c
@pablogsal

Copy link
Copy Markdown
MemberAuthor

Damn, @miss-islington has landed the PR without waiting for the CI to build the last commit I pushed so I created #96433.

@pablogsal

Copy link
Copy Markdown
MemberAuthor

Thanks, everyone for the fantastic reviews and for helping to get this feature ready ❤️

You all rock 🤘

@pablogsal

Copy link
Copy Markdown
MemberAuthor

@erlend-aasland You can make the doc improvement PR after #96433 lands.

@jjerphan

Copy link
Copy Markdown
Contributor

Thanks for all for pushing for better interoperability with perf(1). I highly appreciate this contribution. 🙏

@vstinner

Copy link
Copy Markdown
Member

Nice feature!

There is a typo in sys.deactivate_stack_trampoline() docstring: "Dectivate the perf profiler trampoline": Deactivate.


In the doc, python -m sysconfig | grep HAVE_PERF_TRAMPOLINE can be replaced with python -c "import sysconfig; print(bool(sysconfig.get_config_var('PY_HAVE_PERF_TRAMPOLINE')))" to not rely on the external grep command. At least, I suggest to add PY_ to fix the variable name:

python -m sysconfig | grep PY_HAVE_PERF_TRAMPOLINE

The second command can be replaced with python -c "import sysconfig; print('no-omit-frame-pointer' in sysconfig.get_config_var('PY_CORE_CFLAGS'))".

@erlend-aasland

Copy link
Copy Markdown
Contributor

There is a typo in sys.deactivate_stack_trampoline() docstring: "Dectivate the perf profiler trampoline": Deactivate.

[...]

See #96445 :)

@rajveerb

Copy link
Copy Markdown

@pablogsal

Is it possible to port these changes, from python 3.12, without breaking to previous python versions, say 3.11, 3.10, 3.9?

Why?
Some libraries use specific versions of python and it will take time until they catch up to 3.12's release. This will defer the insights that can be gained till later on.

@pablogsal

Copy link
Copy Markdown
MemberAuthor

Is it possible to port these changes, from python 3.12, without breaking to previous python versions, say 3.11, 3.10, 3.9?

Is possible, but as these versions are only accepting security fixes or bugfixes we cannot backport new features. This means that if you want you can backport them yourself but you need to maintain a fork of the interpreter.

@art049art049 mentioned this pull request Apr 20, 2023
facebook-github-bot pushed a commit to facebookincubator/cinder that referenced this pull request May 19, 2023
Summary: Backport the perf-trampoline introduced in python/cpython#96123. The perf trampoline doesn't work properly with the JIT, so we have submitted a PR to have a C-API to unify writing to the perf-map files python/cpython#103546.
Reviewed By: czardoz
Differential Revision: D45419843
fbshipit-source-id: 16bd13d7981e48c9eb7bc0e5eef1c1f4748965f6
@ZheaoliZheaoli mentioned this pull request Oct 9, 2023
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

interpreter-core(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

14 participants

@pablogsal@tiran@bedevere-bot@gpshead@jjerphan@vstinner@erlend-aasland@rajveerb@zooba@markshannon@tomytsai1@chalggg@kumaraditya303@miss-islington