perf: run pyperformance in CI and close the gaps it finds by moreal · Pull Request #8663 · RustPython/RustPython · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
4cb919a
Add script to run upstream pyperformance against RustPython
moreal Sep 6, 2026
10d327e
pyperformance: support targeting any Python and comparing catalogs
moreal Sep 6, 2026
cf6b8c3
time: use CLOCK_UPTIME_RAW for monotonic/perf_counter on Apple
moreal Sep 7, 2026
11f8331
vm: derive f_lineno lazily instead of tracking prev_line per instruction
moreal Sep 7, 2026
d2e6d8b
vm: coalesce per-call thread-locals into one FRAME_SLOT_CACHE
moreal Sep 7, 2026
1164140
vm: fold stop/finalizing checks into EVAL_BREAKER
moreal Sep 7, 2026
7779043
gc: set the TRACKED bit with a plain store for freshly allocated objects
moreal Sep 7, 2026
f4781e8
vm: skip thread exception publish when pushing/popping a None exc slot
moreal Sep 7, 2026
66671d8
vm: allocation-free keyword-call fast path and super() MRO walk
moreal Sep 7, 2026
2bace67
builtins: cheaper enumerate and zip iteration
moreal Sep 7, 2026
b795621
_asyncio: cache module objects and use native set/dict operations
moreal Sep 7, 2026
de3006f
_json: add native make_encoder (c_make_encoder)
moreal Sep 7, 2026
35fde2c
perf: use mimalloc as global allocator for rustpython CLI
moreal Sep 7, 2026
e0d6de6
vm: cap dict/set table shrink and compact holes on resize
moreal Sep 7, 2026
16545f1
_functools: add native _lru_cache_wrapper
moreal Sep 7, 2026
d9917ab
sre_engine: ASCII fast path for \d \s \w unicode category checks
moreal Sep 7, 2026
58e5797
vm: skip VM attach for no-op generator/coroutine __del__
moreal Sep 7, 2026
5150706
_asyncio: skip full __import__ dispatch on module-cache hot path
moreal Sep 7, 2026
71503be
vm: skip VM-attach section in with_vm when already on the current int…
moreal Sep 7, 2026
105de35
vm: general sys.modules fast path for vm.import
moreal Sep 7, 2026
a2fd0fb
_asyncio: bypass generic context.run dispatch in task_eager_start
moreal Sep 7, 2026
187f1bd
vm: drop scopeguard::defer! from generator/coroutine resume hot path
moreal Sep 7, 2026
8d82295
vm: run generator bodies through the call trampoline
moreal Sep 7, 2026
3ce7a3e
vm: run a `yield from` chain in one eval loop
moreal Sep 7, 2026
0f9bdb9
vm: reset the oparg prefix when a signal unwinds a frame
moreal Sep 7, 2026
0a9b0ca
bytecode: fetch a code unit with one 16-bit acquire load
moreal Sep 7, 2026
f1aaa09
vm: compute the cache-entry count after dispatch, not before
moreal Sep 7, 2026
b6f3528
vm: move the eval-breaker body out of the dispatch loop
moreal Sep 7, 2026
c3f24db
vm: always inline the eval stack push/pop primitives
moreal Sep 7, 2026
4c7a728
vm: carry the instruction fetch state in loop locals
moreal Sep 7, 2026
d3372c4
bytecode: hoist the instruction array base out of the dispatch loop
moreal Sep 8, 2026
f33054b
common: an immortal bit in the refcount word
moreal Sep 8, 2026
b97d542
vm: make the singletons, small ints, interned strings and static type…
moreal Sep 8, 2026
e648e36
codecs: fast-path utf-8 decode, skipping the codec registry round trip
moreal Sep 8, 2026
2d44f3c
codecs: fast-path utf-8/ascii/latin-1 encode and ascii/latin-1 decode
moreal Sep 8, 2026
0733c34
vm: make the runtime safe for borrowed stack entries
moreal Sep 8, 2026
f949a12
vm: read consumed stack entries in place instead of owning them
moreal Sep 8, 2026
23979f6
vm: turn LOAD_FAST_BORROW into an actual borrow
moreal Sep 8, 2026
b88b571
vm: exact-dict fast path for DICT_MERGE and CALL_FUNCTION_EX kwargs
moreal Sep 8, 2026
a3df72c
vm: skip the recursion guard hashing exact ints inside a tuple
moreal Sep 8, 2026
a126a94
vm: wire slot descriptors from __slots__ into C-level type slots
moreal Sep 8, 2026
1b3d1fd
pyexpat: add UseForeignDTD, fix silently swallowed handler exceptions
moreal Sep 8, 2026
c5a05b0
pyexpat: support multi-chunk Parse()/ParseFile() feeds
moreal Sep 8, 2026
5e244fa
frame: stop allocating cold data to close a generator
moreal Sep 8, 2026
df078a2
function: bind exact args straight into a generator's frame
moreal Sep 8, 2026
141f87c
frame: drain a dead frame in place instead of moving it out
moreal Sep 8, 2026
c90081b
vm: don't raise a TypeError to ask an iterator for its length
moreal Sep 8, 2026
3c7b479
gc: track a generator and its frame in one pass
moreal Sep 8, 2026
8d0ebf9
test: drop stale expectedFailure markers fixed by the pyexpat changes
moreal Sep 8, 2026
eade737
pyexpat: drive a single background EventReader for true incremental P…
moreal Sep 8, 2026
e5c7634
pyexpat: add a Sync fallback backend for targets without threads
moreal Sep 8, 2026
c5c8090
_pickle: native Pickler, Unpickler and PickleBuffer
moreal Sep 8, 2026
7b69fd0
_pickle: raise the pickle.find_class audit event
moreal Sep 8, 2026
1ac89d4
_pickle: avoid temporary buffers on the save fast paths
moreal Sep 8, 2026
baafe8e
pyexpat: make the threaded backend fork-safe
moreal Sep 8, 2026
1059850
pyexpat: implement name interning via self.intern, matching libexpat
moreal Sep 8, 2026
88e722f
_elementtree: native Element, SubElement and ParseError
moreal Sep 8, 2026
d0b8045
_elementtree: native TreeBuilder and XMLParser
moreal Sep 8, 2026
6f4396f
pyexpat: stop rescanning the whole line per position query
moreal Sep 8, 2026
65c509f
_elementtree: charge Element.__deepcopy__ to the recursion budget
moreal Sep 8, 2026
812d3f3
pyexpat: don't let a stale NeedMore end a Parse() early
moreal Sep 8, 2026
66a24e8
dict_inner: fast-path exact-int equality in key_eq
moreal Sep 8, 2026
117826a
vm: let the modulus type handle a three-argument pow
moreal Sep 8, 2026
96c0bfc
decimal: add a native arbitrary-precision decimal engine
moreal Sep 8, 2026
b6f1fd7
_decimal: ship the native engine as decimal's accelerator
moreal Sep 8, 2026
0647ee9
vm: add a feature-gated opcode-pair histogram
moreal Sep 8, 2026
ab86664
vm: let boolean producers run the branch that follows them
moreal Sep 8, 2026
08a9726
ci: compare base, head and CPython with pyperformance on one runner
moreal Sep 8, 2026
e068bfb
ci: comment from the pyperformance run itself when the PR allows it
moreal Sep 8, 2026
3266846
ci: address zizmor findings and fall back to head vs. CPython
moreal Sep 8, 2026
06a3415
fix: clear the clippy lints this branch introduced
moreal Sep 8, 2026
c727056
fix: keep the ospath gate and let unbounded division and power stay e…
moreal Sep 8, 2026
307e346
fix: don't build a power of ten that dwarfs what it divides
moreal Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .cspell.dict/cpython.txt
9 changes: 9 additions & 0 deletions .cspell.dict/rustpython.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
atfork
cfgs
csascii
csisolatin
genshi
mimalloc
miri
py
pyarg
Expand All @@ -19,6 +24,7 @@ pyname
pyobj
pyobject
pypayload
pyperformance
pyref
pyslot
pystaticmethod
Expand All @@ -30,4 +36,7 @@ pytype
qsbr
rustix
struc
unallocatable
unscanned
untrapped
zelf
65 changes: 65 additions & 0 deletions .github/workflows/pyperformance-comment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
on:
workflow_run:
workflows: [pyperformance]
types: [completed]

name: pyperformance comment

# Same split as `codspeed-comment.yaml`: a `pull_request` run from a fork gets
# a read-only token however it is configured, so the comparison is computed
# there and handed over as an artifact, and this workflow -- which
# `workflow_run` always runs in the base repo's context -- is the one trusted
# with a token that may write the comment.
permissions:
contents: read
pull-requests: write

jobs:
comment:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
steps:
- name: Download the comparison produced by the pyperformance workflow
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: pyperformance-diff
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ github.token }}
continue-on-error: true # absent when the job was skipped or dispatched

- name: Post or update the PR comment
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const fs = require('fs');
if (!fs.existsSync('diff.md') || !fs.existsSync('pr_number.txt')) {
core.info('No diff.md/pr_number.txt in this run; nothing to comment.');
return;
}

const prNumber = parseInt(fs.readFileSync('pr_number.txt', 'utf8').trim(), 10);
const body = fs.readFileSync('diff.md', 'utf8');
const marker = '<!-- pyperformance-local-diff -->';

const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const existing = comments.find((c) => c.body && c.body.includes(marker));

if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
}
220 changes: 220 additions & 0 deletions .github/workflows/pyperformance.yaml
Loading
Loading