python / python/cpython

Eliminate overhead of fetching and testing `NULL` attributes in `STORE_ATTR` specializations for new objects

Aperta
#144,141 3 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

interpreter-core performance
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Consider

class C:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
C(1,2,3)

This produces a trace looking something like this:

...
_CHECK_AND_ALLOCATE_OBJECT
_CREATE_INIT_FRAME
_PUSH_FRAME
# Some guards
_LOAD_FAST_BORROW_1
_LOAD_FAST_BORROW_0
# Some more guards
_STORE_ATTR_INSTANCE_VALUE
# Some more guards
_LOAD_FAST_BORROW_2
_LOAD_FAST_BORROW_0
# Some more guards
_STORE_ATTR_INSTANCE_VALUE
# Some more guards
_LOAD_FAST_BORROW_3
_LOAD_FAST_BORROW_0
# Some more guards
_STORE_ATTR_INSTANCE_VALUE
...

Each of those _STORE_ATTR_INSTANCE_VALUE reads the old value out of memory and then conditionally decrefs it.
But in this case we know that the old value was NULL so we can just overwrite it.
So we can replace this:

        PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
        PyObject *old_value = *value_ptr;
        FT_ATOMIC_STORE_PTR_RELEASE(*value_ptr, PyStackRef_AsPyObjectSteal(value));
        if (old_value == NULL) {
            PyDictValues *values = _PyObject_InlineValues(owner_o);
            Py_ssize_t index = value_ptr - values->values;
            _PyDictValues_AddToInsertionOrder(values, index);
        }
        Py_XDECREF(old_value);

with this:

        PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
        FT_ATOMIC_STORE_PTR_RELEASE(*value_ptr, PyStackRef_AsPyObjectSteal(value));
        PyDictValues *values = _PyObject_InlineValues(owner_o);
        Py_ssize_t index = value_ptr - values->values;
       _PyDictValues_AddToInsertionOrder(values, index);

On Aarch64, this reduces the number of machine instructions from 48 to 26.

The same reasoning also applies to _STORE_ATTR_SLOT where it reduces the number of machine instructions from 32 to 14.

See also https://github.com/python/cpython/issues/134584

We can probably remove some of those guards as well, but that's a separate issue.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia individuando le specializzazioni dell’interprete CPython denominate STORE_ATTR_INSTANCE_VALUE e STORE_ATTR_SLOT, quindi leggi la issue correlata 134584 per il contesto. Confronta la loro gestione degli oggetti appena allocati con i percorsi proposti e verifica che la modifica mantenga la gestione dell’ordine di inserimento eliminando al contempo le letture di NULL, i decref e l’overhead di istruzioni segnalato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
c, python
Ambito
backend, performance
Tipo di issue
Refactoring
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.