38 points par GN⁺ 2026-01-02 | Aucun commentaire pour le moment. | Partager sur WhatsApp
  • Résultats de benchmark mesurant de façon systématique les performances en calcul, mémoire et entrées/sorties de Python, avec une quantification du temps et de la mémoire consommée par chaque opération
  • Du point de vue de la vitesse, l’article présente les latences relatives de diverses opérations : accès à un attribut en 14 ns, ajout à une liste en 29 ns, ouverture d’un fichier en 9 μs, réponse FastAPI en 8,6 μs, etc.
  • Du point de vue de la mémoire, il donne des chiffres précis : chaîne vide 41 octets, entier 28 octets, liste vide 56 octets, dictionnaire vide 64 octets, processus vide 16 MB, etc.
  • Il compare, selon les domaines comme les structures de données, la sérialisation et le traitement asynchrone, les écarts de performances entre la bibliothèque standard et des bibliothèques alternatives (orjson, msgspec, etc.)
  • Parmi les enseignements clés : l’importante surcharge mémoire des objets Python, la rapidité des recherches dans les dict/set, l’effet de réduction mémoire de __slots__, et la nécessité de prendre en compte le surcoût de l’asynchrone

Vue d’ensemble

  • Document récapitulant les indicateurs de performance que les développeurs Python devraient connaître, avec des mesures réelles de vitesse d’exécution et d’usage mémoire
  • Les benchmarks ont été réalisés dans un environnement CPython 3.14.2, Mac Mini M4 Pro (ARM, 14 cœurs, 24 GB de RAM)
  • Les résultats mettent l’accent sur la comparaison relative, et le code comme les données sont publiés dans un dépôt GitHub

Utilisation mémoire (Memory Costs)

  • Un processus Python vide consomme 15,73 MB de mémoire
  • Les chaînes de caractères ont une base de 41 octets, avec 1 octet supplémentaire par caractère
    • Ex. : chaîne vide 41B, chaîne de 100 caractères 141B
  • Les types numériques : petits entiers (0–256) 28B, grands entiers (1000) 28B aussi, très grands entiers (10ⁱ⁰⁰) 72B, flottants 24B
  • Taille de base des collections : liste 56B, dictionnaire 64B, set 216B
    • Avec 1 000 éléments : liste 35,2 KB, dictionnaire 63,4 KB, set 59,6 KB
  • Instances de classes : classe classique (5 attributs) 694B, classe avec __slots__ 212B
    • Pour 1 000 instances : classe classique 165,2 KB, classe __slots__ 79,1 KB

Opérations de base (Basic Operations)

  • Opérations arithmétiques : addition d’entiers 19 ns, addition de flottants 18,4 ns, multiplication d’entiers 19,4 ns
  • Opérations sur les chaînes : concaténation 39,1 ns, f-string 64,9 ns, .format() 103 ns, formatage % 89,8 ns
  • Opérations sur les listes : append() 28,7 ns, compréhension de liste (1 000 éléments) 9,45 μs, boucle for équivalente 11,9 μs
    • La compréhension de liste est environ 26 % plus rapide qu’une boucle for

Accès et itération sur les collections (Collection Access and Iteration)

  • Accès par clé/index : recherche dans un dictionnaire 21,9 ns, test d’appartenance dans un set 19 ns, accès par index dans une liste 17,6 ns
    • Le test d’appartenance dans une liste (1 000 éléments) prend 3,85 μs, soit environ 200 fois plus lent que dans un set/dictionnaire
  • Vérification de longueur : len() prend 18,8 ns pour une liste, 17,6 ns pour un dictionnaire, 18 ns pour un set
  • Itération : liste (1 000 éléments) 7,87 μs, dictionnaire 8,74 μs, sum() 1,87 μs

Classes et attributs (Class and Object Attributes)

  • Vitesse d’accès aux attributs : lecture à 14,1 ns aussi bien pour une classe classique que pour une classe __slots__, écriture autour de 16 ns
  • Autres opérations : lecture via @property 19 ns, getattr() 13,8 ns, hasattr() 23,8 ns
  • Avec __slots__, le gain mémoire dépasse 2x, tandis que la vitesse d’accès reste comparable

JSON et sérialisation (JSON and Serialization)

  • Performances des bibliothèques alternatives par rapport à la bibliothèque standard
    • orjson sérialise un objet complexe en 310 ns, soit plus de 8 fois plus vite que json à 2,65 μs
    • msgspec atteint 445 ns, ujson 1,64 μs
  • En désérialisation aussi, orjson est le plus rapide avec 839 ns
  • Pydantic : model_dump_json() 1,54 μs, model_validate_json() 2,99 μs

Frameworks web (Web Frameworks)

  • À réponse JSON identique : FastAPI 8,63 μs, Starlette 8,01 μs, Litestar 8,19 μs, Flask 16,5 μs, Django 18,1 μs
  • FastAPI répond environ 2 fois plus vite que Django

Entrées/sorties fichier (File I/O)

  • Ouverture/fermeture d’un fichier : 9,05 μs, lecture de 1 KB : 10 μs, lecture de 1 MB : 33,6 μs
  • Écriture : 1 KB 35,1 μs, 1 MB 207 μs
  • Pickle est environ 2 fois plus rapide que json en sérialisation comme en désérialisation (pickle.dumps() 1,3 μs, json.dumps() 2,72 μs)

Base de données et persistance (Database and Persistence)

  • SQLite : insert 192 μs, select 3,57 μs, update 5,22 μs
  • diskcache : set 23,9 μs, get 4,25 μs
  • MongoDB : insert 119 μs, find_one 121 μs
  • SQLite est le plus rapide en lecture, tandis que diskcache excelle en écriture

Appels de fonction et exceptions (Function and Call Overhead)

  • Appels de fonction : fonction vide 22,4 ns, méthode 23,3 ns, lambda 19,7 ns
  • Gestion des exceptions : try/except (cas normal) 21,5 ns, exception levée 139 ns
  • Vérification de type : isinstance() 18,3 ns, comparaison type() 21,8 ns

Surcoût de l’asynchrone (Async Overhead)

  • Création de coroutine 47 ns, run_until_complete 27,6 μs
  • asyncio.sleep(0) 39,4 μs, gather(10 coroutines) 55 μs
  • Par rapport à un appel de fonction synchrone (20 ns), une exécution asynchrone (28 μs) est environ 1 000 fois plus lente

Enseignements clés (Key Takeaways)

  • La surcharge mémoire des objets Python est importante, même une liste vide consomme 56 octets
  • Les recherches dans les dictionnaires et sets sont des centaines de fois plus rapides qu’un parcours de liste
  • Les bibliothèques JSON alternatives comme orjson et msgspec sont 3 à 8 fois plus rapides que la solution standard
  • Le traitement asynchrone a un surcoût élevé et n’est recommandé que lorsqu’une exécution concurrente est nécessaire
  • __slots__ permet de réduire la mémoire de plus de moitié avec une perte de performance quasi nulle

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.