python / python/cpython

Improve performance of dataclasses.asdict by caching field names

Offen
#138,232 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

performance stdlib topic-dataclasses type-feature
Vorherrschende Sprache
Python
Sterne
77.2k
Forks
35.9k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Feature or enhancement

Proposal:

About 8 years ago @ericvsmith asked:

https://github.com/python/cpython/blob/c779f2324df06563b4ba3d70d0941e619ccaf5ff/Lib/dataclasses.py#L1381

By caching the field names of a dataclass on the class the performance improves:

asdict: Mean +- std dev: [main] 2.33 us +- 0.14 us -> [pr] 1.65 us +- 0.08 us: 1.41x faster
astuple: Mean +- std dev: [main] 2.77 us +- 0.15 us -> [pr] 2.15 us +- 0.09 us: 1.29x faster
f.__getstate__(): Mean +- std dev: [main] 941 ns +- 64 ns -> [pr] 360 ns +- 18 ns: 2.61x faster

Benchmark hidden because not significant (1): instance creation

Geometric mean: 1.47x faster
Test script

(executed on non-pgo build)

import pyperf

setup = """
from dataclasses import dataclass, asdict, astuple
from pickle import dumps

@dataclass
class Simple:
     i : int
     s : str
     l : list

s = Simple(10, 'hi', [3, 1, 4, 1])

@dataclass(frozen=True, slots=True)
class Frozen:
     i : int
     s : str
     l : list

f = Frozen(10, 'hi', [3, 1, 4, 1])
f.__getstate__()

"""

runner = pyperf.Runner()
runner.timeit(name="instance creation", stmt="Simple(10, 'hi', [3, 1, 4, 1])", setup=setup)
runner.timeit(name="asdict", stmt="asdict(s)", setup=setup)
runner.timeit(name="astuple", stmt="astuple(s)", setup=setup)
runner.timeit(name="f.__getstate__()", stmt="f.__getstate__()", setup=setup)

The main downside of caching the field names is that (per dataclass, not per instance) we have an additional private field on the class with a list of strings.

Has this already been discussed elsewhere?

No response given

Links to previous discussion of this feature:

No response

Linked PRs
  • gh-138233

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne damit, Lib/dataclasses.py im Bereich der Implementierung von asdict und astuple zu prüfen, und sieh dir anschließend den verknüpften PR gh-138233 an, bevor du irgendwelche Arbeiten durchführst. Führe das bereitgestellte pyperf-Skript aus, um die gemeldete Baseline festzulegen; die Fertigstellung sollte das Verhalten von dataclass beibehalten und gleichzeitig die vorgeschlagene Performance-Verbesserung durch das Caching von Feldnamen erreichen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
performance
Issue-Typ
Feature
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
25/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.