Reduce overhead of PyErr_CheckSignals
Personne n'a encore pris cette issue.
- Langage dominant
- Python
- Étoiles
- 77.2k
- Forks
- 35.9k
- Métriques de merge des PR
- Métriques de PR en attente
Description
Feature or enhancement
Proposal:
PyErr_CheckSignals() is the API long-running C loops use to stay interruptible. In the common case (no signal arrived) the call currently does, in order:
_PyRunRemoteDebugger()(since gh-131591, 3.14): a call that fetches the interpreter config via_PyInterpreterState_GetConfig()before looking at the pending flag;_Py_ThreadCanHandleSignals():_Py_IsMainThread()callsPyThread_get_thread_ident()and thereforepthread_self(), plus_Py_IsMainInterpreter();- only then
_PyErr_CheckSignalsTstate(), whose first line is the cheapis_trippedtest that returns immediately.
That is about 100 instructions per call.
Proposal
Test the cheap flags first, without changing what is done when they are set:
_PyErr_CheckSignalsTstate()does the main-thread check itself, after its existingis_trippedtest, soPyErr_CheckSignals()and the eval loop just call it; the handler-running body moves to an out-of-line helper so the early return stays cheap;_PyRunRemoteDebugger()testsdebugger_pending_callbefore fetching the config.
Results
Non-PGO build, pyperf:
| Benchmark | main | branch |
|---|---|---|
| str(12345) | 68.6 ns | 56.8 ns: 1.21x faster |
| repr(list(range(100))) | 3.06 us | 2.36 us: 1.29x faster |
| ', '.join(map(str, range(100))) | 6.90 us | 5.67 us: 1.22x faster |
| '%s=%r' % (k, v) | 192 ns | 177 ns: 1.08x faster |
| print(*range(100), file=f) | 15.6 us | 13.5 us: 1.16x faster |
| csv.writer: 100 rows of 10 ints | 72.5 us | 60.1 us: 1.21x faster |
| repr(dataclass with 5 fields) | 805 ns | 720 ns: 1.12x faster |
| a * b (10 x 10 digits) | 159 ns | 102 ns: 1.56x faster |
| a // c (10 // 2 digits) | 151 ns | 121 ns: 1.24x faster |
Notes: the gain for the arithmetic cases are not too important, they can be handled directly as well. See https://github.com/python/cpython/issues/157742.
Has this already been discussed elsewhere?
Related: gh-131591, gh-133465
Has this already been discussed elsewhere?
No response given
Links to previous discussion of this feature:
No response
Linked PRs
- gh-157748
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par lire PyErr_CheckSignals(), _PyErr_CheckSignalsTstate() et _PyRunRemoteDebugger(), en vous concentrant sur l’ordre indiqué des vérifications peu coûteuses des flags et de la gestion des signaux. Comparez le comportement proposé et les benchmarks avec la PR liée gh-157748 ; l’issue est terminée lorsque le chemin sans signal est moins coûteux, sans modifier le comportement lorsque les flags sont définis.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- c, python
- Domaine
- performance
- Type d'issue
- Fonctionnalité
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Clairement spécifiée
- Accessibilité débutants
- 25/100