GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — inspect.getframeinfo and traceback build every preceding co_positions() tuple · Issue #161799 · python/cpython

inspect.getframeinfo and traceback build every preceding co_positions() tuple #161799

New issue
Copy link
New issue
Copy link
Open
Open
inspect.getframeinfo and traceback build every preceding co_positions() tuple#161799
Copy link
Labels
pendingThe issue will be closed if no feedback is providedThe issue will be closed if no feedback is providedperformancePerformance or resource usagePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancementA feature request or enhancement

Description

@xionghul
xionghul
opened on Nov 11, 2026
Issue body actions

Bug report

inspect.getframeinfo() and traceback read the position of the current instruction with:

next(itertools.islice(code.co_positions(), instruction_index // 2, None))

co_positions() yields one tuple per instruction. islice has to build and discard a tuple for every preceding instruction before it can return the requested one. The returned position is correct. The cost grows with the size of the code object.

inspect.stack(0) does this for every frame. context=0 only skips the source-line listing. It still computes the PEP 657 position. A caller that uses inspect.stack(0) on a hot path therefore pays for a full walk of each frame's line table.

On 3.11 and on current main, a short function and a function with about 2500 statements show the difference:

import inspect
import timeit

def make(n):
    src = "def f():\n" + "    x = 1\n" * n + "    return inspect.stack(0)\n"
    ns = {"inspect": inspect}
    exec(src, ns)
    return ns["f"]

small, large = make(10), make(2500)
print("small", timeit.timeit(small, number=2000) / 2000)
print("large", timeit.timeit(large, number=200) / 200)

The byte offset passed in is f_lasti or tb_lasti, the same value traceback.c already passes to PyCode_Addr2Location. One call of that function fills the same (start_line, end_line, start_column, end_column) tuple, with None where co_positions() yields None.

A direct lookup for real code objects removes the per-instruction tuple. Objects that only implement co_positions(), such as the stand-ins in test_traceback, can keep the iterator path.

CPython versions tested on:

3.11, CPython main branch

Operating systems tested on:

No response

Linked PRs

  • gh-161799: Look up one bytecode position in inspect and traceback #161800

Activity

  1. xionghul
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Nov 11, 2026
  2. aisk
    added
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    on Nov 11, 2026
  3. picnixz commented on Nov 11, 2026

    @picnixz
    picnixz
    on Nov 11, 2026
    Member
    More actions

    I'm not convinced by this change. How "slow" is it? those are inspection tools and thus I don't think we should add private C methods just for that.

  4. picnixz
    added
    type-featureA feature request or enhancementA feature request or enhancement
    performancePerformance or resource usagePerformance or resource usage
    pendingThe issue will be closed if no feedback is providedThe issue will be closed if no feedback is provided
    and removed
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Nov 11, 2026
  5. picnixz commented on Nov 11, 2026

    @picnixz
    picnixz
    on Nov 11, 2026
    Member
    More actions

    On 3.11 and on current main, a short function and a function with about 2500 statements show the difference:

    Please post the actual numbers. Determine whether they were done on a PGO+LTO/release build. Debug builds are not relevant when it comes down to performance evaluation.

  6. xionghul commented on Nov 12, 2026

    @xionghul
    xionghul
    on Nov 12, 2026
    Author
    More actions

    small 0.00013875
    large 0.00074843

    3.11.6 (main, Oct 3 2023, 01:26:22) [Clang 17.0.1] with PGO+LTO/release build.

  7. picnixz commented on Nov 12, 2026

    @picnixz
    picnixz
    on Nov 12, 2026
    Member
    More actions

    What about the timing on main? note that 3.11 would not be changed since it is security only. I wonder how frequent inspect.stack(0) is done in a hot path. Is it a feature request because it affects a real product or is this purely theoretical?

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

    pendingThe issue will be closed if no feedback is providedThe issue will be closed if no feedback is providedperformancePerformance or resource usagePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancementA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.