Comments on: Mesurer les performances d’un snippet Python http://sametmax.com/mesurer-les-performances-dun-snippet-python/ Du code, du cul Sat, 07 Nov 2015 11:08:18 +0000 hourly 1 http://wordpress.org/?v=4.1 By: Etienne http://sametmax.com/mesurer-les-performances-dun-snippet-python/#comment-10013 Wed, 12 Jun 2013 12:17:59 +0000 http://sametmax.com/?p=6369#comment-10013 @ Badeu
T’as raison, l’opcode est pas identique.

Mais il y a un problème avec:
## Long dictionaries
## Default merge strategy
## 1 54.5233860016
## 3 70.213809967

Chez moi c’est plutôt de l’ordre de :
## Long dictionaries
## Default merge strategy
## 1 78.3221180439
## 3 77.8049631119

Un léger avantage pour dmerge3

]]>
By: Badeu http://sametmax.com/mesurer-les-performances-dun-snippet-python/#comment-10008 Wed, 12 Jun 2013 10:05:43 +0000 http://sametmax.com/?p=6369#comment-10008 Quand on regarde d’un peu plus près au code généré, il n’est pas tout à fait identique entre dmerge1 et dmerge3.

pour dmerge1, d est accédé avec des LOAD_DEREF et STORE_DEREF, pour dmerge3 avec des LOAD_FAST et STORE_FAST Ce qui semble logique vu que le générateur fait une closure sur d dans dmerge1.

Je reste juste étonné de l’impact que ça a.

]]>
By: kontre http://sametmax.com/mesurer-les-performances-dun-snippet-python/#comment-9984 Tue, 11 Jun 2013 17:24:19 +0000 http://sametmax.com/?p=6369#comment-9984 My bad, j’ai bêtement zappé un return.
[mauvaise foi] Mais aussi la bonne pratique de n’avoir qu’un point de sortie n’est pas respectée, on s’y perd ! [/mauvaise foi]

]]>
By: Etienne http://sametmax.com/mesurer-les-performances-dun-snippet-python/#comment-9954 Tue, 11 Jun 2013 10:41:14 +0000 http://sametmax.com/?p=6369#comment-9954 @ Kontre, Badeu

Comme il s’agit de la “Default merge strategy”, le code passe pas par le générateur de dmerge1 ou le for de dmerge3. Donc le problème est pas là.

J’ai essayé ça avec le code copié ci-dessus (les versions avec les expressions génératrices):

if __name__ == "__main__":
    import random
    import timeit
 
    print('Generate test dicts')
    d3 = {random.randint(0, 10000000): 'd1' for x in xrange(1000000)}
    d4 = {random.randint(0, 10000000): 'd2' for x in xrange(1000000)}
    print("Start timing")
    setup = '''from __main__ import (dmerge1, dmerge2, dmerge3, dmerge4,
       d3, d4)'''
    print ("Long dictionaries")
    print ("Default merge strategy")
    print ("1", timeit.timeit("dmerge1(d3, d4)", setup=setup, number=100))
    print ("3", timeit.timeit("dmerge3(d3, d4)", setup=setup, number=100))
 
## Generate test dicts
## Start timing
## Long dictionaries
## Default merge strategy
## 1 79.4722130299
## 3 79.2059469223

Les résultats sont identiques (ouf…). Donc le problème est de ton côté: soit le code des deux fonctions est pas identique, soit les conditions des deux tests sont pas les mêmes.

]]>
By: kontre http://sametmax.com/mesurer-les-performances-dun-snippet-python/#comment-9932 Mon, 10 Jun 2013 21:14:24 +0000 http://sametmax.com/?p=6369#comment-9932 C’est le même algo mais ça ne fait pas la même chose : les générateurs sont plus rapides que les boucles for génériques. C’est relativement logique : c’est moins général, il y a moins de cas différents, donc on peut plus optimiser.

On a toujours des surprises avec le profiling…

]]>
By: Badeu http://sametmax.com/mesurer-les-performances-dun-snippet-python/#comment-9921 Mon, 10 Jun 2013 09:40:19 +0000 http://sametmax.com/?p=6369#comment-9921 Moralité, la prochaine fois je pousserai pas du code écrit en 10 secondes et pas testé.

Par contre un truc me turlupine toujours. Parce qu’au final en réessayant d’optimiser après la première série de tests de perf sur github, je suis aussi arrivé à la solution du deuxième dmerge1 (et je me disais putain ça va tout arracher c’est obligatoire !! quelle naiveté)


## Long dictionaries
## Default merge strategy
## 1 54.5233860016
## 3 70.213809967

WTF ?! J’ai exécuté les tests de performances un paquet de fois, et ça se vérifie toujours. Pourtant dans ce cas, le code de dmerge1 et dmerge3 est identique.

]]>