gh-157742: Check for signals every 64th iteration in the int arithmetic loops #157744

Open
eendebakpt opened 4:38am on September 18, 2026 wants to merge 24 Ξ” into python/cpython main from
longobject-sigcheck-batch
Reviewing
11 fewer changed lines
(69% less) vs GitHub
This saves about 120.7 hours per year vs conventional diff tools
eendebakpt and 1 other authored
of work during September 18
Diff Delta:
24
About 88 Diff Delta/hour
Classified as:  General

eendebakpt's Description of Work

x_mul() checks for signals on every row, x_divrem() on every quotient digit and the decimal string conversion on every digit. PyErr_CheckSignals() costs about as much as a hundred digit operations, so for small operands the checks cost more than the arithmetic.

SIGCHECK() now takes the loop index and checks on every 64th iteration, the same pattern _sre uses.

| Benchmark | main | PR |
|---|:---:|:---:|
| a * b (10 x 10 digits) | 159 ns | 97.2 ns: 1.64x faster |
| a * b (60 x 60 digits) | 2.61 us | 2.22 us: 1.18x faster |
| a * b (500 x 500 digits) | 99.1 us | 79.7 us: 1.24x faster |
| a // b (1000 // 2 digits) | 13.8 us | 10.3 us: 1.34x faster |
| a // b (1000 // 500 digits) | 204 us | not significant |
| pow(3, 5000) | 10.7 us | 8.38 us: 1.28x faster |
| math.factorial(2000) | 97.7 us | 81.6 us: 1.20x faster |
| str(7**1000) | 8.07 us | 7.34 us: 1.10x faster |

Benchmark script

```python
import pyperf

runner = pyperf.Runner()
def ints(na, nb):
return (f"import random; r = random.Random(1); "
f"a = r.getrandbits({na*30-1}) | (1 << {na*30-2}); "
f"b = r.getrandbits({nb*30-1}) | (1 << {nb*30-2})")
runner.timeit("a * b (10 x 10 digits)", "a * b", setup=ints(10, 10))
runner.timeit("a * b (60 x 60 digits)", "a * b", setup=ints(60, 60))
runner.timeit("a * b (500 x 500 digits)", "a * b", setup=ints(500, 500))
runner.timeit("a // b (1000 // 2 digits)", "a // b", setup=ints(1000, 2))
runner.timeit("a // b (1000 // 500 digits)", "a // b", setup=ints(1000, 500))
runner.timeit("pow(3, 5000)", "pow(3, 5000)")
runner.timeit("math.factorial(2000)", "factorial(2000)",
setup="from math import factorial")
runner.timeit("str(7**1000)", "str(x)", setup="x = 7**1000")
```

Generated with Claude Code


  • Issue: gh-157742
    <!-- /gh-issue-number -->

2 total changed files
(1 file ignored)
Loading changes...
You’ve reached the end
The diff well is dry.