Skip to content

Python 3.15 produces incompatible Jitdumps on MacOS #150723

Closed

Description

@not-matthias

Bug report

Bug description:

See: mstange/samply#826 and mstange/linux-perf-data#27

Reproduction with samply

fib.py:

def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(36))

Works: Just using the perf-map resolves py::fib:

PYTHONPERFSUPPORT=1 samply record -- python3.15 fib.py

However, when emitting the jitdumps, we see a ton of unresolved 0x... frames and no py::fib:

PYTHON_PERF_JIT_SUPPORT=1 samply record -- python3.15 fib.py

The issue

CPython 3.15 introduces Jitdump support on MacOS: #136461

This PR also changed the struct layout:

#if defined(__APPLE__)
uint64_t thread_id; // Thread ID where code was generated
#else
uint32_t thread_id; // Thread ID where code was generated
#endif

#if defined(__APPLE__)
    uint64_t thread_id;      // Thread ID where code was generated
#else
    uint32_t thread_id;      // Thread ID where code was generated
#endif

This is not compatible with the original linux perf data specification, which almost all profilers/tools rely on. I highly recommend fixing this, otherwise profilers won't be able to take advantage of jitdumps.

CPython versions tested on:

3.15

Operating systems tested on:

macOS

Linked PRs

Activity

  1. canova commented on Jun 1, 2026

    @canova
    Contributor

    Thanks a lot for filing this bug! This is indeed a problem, and I was just typing an issue message for this.

    Jitdump support on macOS was implemented in #136461.

    While I was working on that PR I changed this jitdump struct to hold a uint64_t value for thread_id on macOS.

    This was due to the fact that pthread_threadid_np returned uint64_t instead of uint32_t. It's captured here:

    pthread_threadid_np(NULL, &ev.thread_id);

    But this was wrong! jitdump file format specifically mentions that this has to be uint32_t:
    https://github.com/torvalds/linux/blob/e43ffb69e0438cddd72aaa30898b4dc446f664f8/tools/perf/Documentation/jitdump-specification.txt#L74

    So we need to force macOS to also store uint32_t as well to keep the layout same. Samply's author @mstange mentioned that this thread_id is not used for anything: mstange/linux-perf-data#27 (comment) So we can just truncate the uint64_t value that we get.

    cc @pablogsal

  2. canova commented on Jun 1, 2026

    @canova
    Contributor

    I was working on a patch locally and realized that this fix alone is not enough. It looks like there is a secondary issue.

    It looks like it's because of the timestamp domain mismatch. Currently python records the jitdump timestamps with clock_gettime(CLOCK_MONOTONIC). On Linux that's fine because the consumers (perf and samply) timestamps its samples with CLOCK_MONOTONIC too, so the records and samples share a clock.

    On macOS though, samply timestamps its samples with mach_absolute_time(). Those are different clock domains:
    CLOCK_MONOTONIC keeps advancing while the machine is asleep, mach_absolute_time()
    does not. For example, on my machine they differ by ~28 days of accumulated sleep. That's why we have to use mach_absolute_time also on the python side when we are recording our jit dump records on macOS.

    Currently other jitdump producers like SpiderMonkey, v8, JavaScriptCore, etc. all output their timestamps with mach_absolute_time on macOS. So I think it makes sense for python to align there as well.

    TBH, I should have tested this code path more properly. I was mostly focusing on PYTHONPERFSUPPORT and neglected PYTHON_PERF_JIT_SUPPORT. Sorry about that!

  3. added a commit that references this issue on Jun 3, 2026
  4. added a commit that references this issue on Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions