Euh, je pense que si tu modifies la fonction qui va le plus lentement et que tu obtiens une plus grosse différence de performance, c'est que tu n'as pas fait une optimisation, mais au contraire que tu as agravé la situation hein.
Est ce qu'on a envie d'apprendre aux gens comment écrire du code efficace, et quelles sont les sources potentielles de lenteur dans un programme ? Je pense que oui. Pour qu'ils comprennent par exemple que transformer un programme avec des appels de fonction en un programme avec des sauts, ce n'est pas
Ce ne sont pas "quelques spills en plus", ce sont des appels de fonction. Et un appel de fonction (avec son incrément de la pile, son saut, son décrément, son retour), ça coute cher, surtout face à une multiplication ! Encore une fois, 25% de gain de performance, ce n'est pas une "différence de performance fragile peu justifiée"...
J'aimerai bien savoir comment tu justifies qu'un gain de 25% sur un code numérique n'a aucune intéret...
Bien sur que non. Par exemple quand on construit des listes, puisqu'à chaque tour de boucle/appel de fonction, on alloue sur le tas, on passe dans le GC, on suit des pointeurs non contigües en mémoire, il est clair que dans ces cas là, le seul intéret d'être tail rec est de ne pas faire exploser la pile, pas de gagner en terme de performance. Pour du code numérique, encore une fois, c'est différent.
Du genre "le corps de la boucle est vraiment pas cher, donc l'appel de fonction a un cout loin d'être négligeable" ?
Alors là, j'aimerais vraiment bien savoir comment tu as fait tes tests...
J'ai pour non tail rec
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 let rec ntr_pow x y = if y = 0 then 1. else let xy2 = ntr_pow x (y / 2) in if y mod 2 = 1 then xy2 *. xy2 *. x else xy2 *. xy2 let tr_pow x y = let rec aux xpow res y = if y = 0 then res else aux (xpow *. xpow) (if y mod 2 = 1 then res *. xpow else res) (y / 2) in aux x 1. y let nothing x y = x let f = tr_pow let _ = for i = 1 to 10000000 do for j = 1 to 32 do let _ = f 42. j in () done done
Real: 19.50s User: 19.44s System: 0.03s Percent: 99% Cmd: ./ntr_pow
et pour tail rec
Real: 16.56s User: 16.49s System: 0.02s Percent: 99% Cmd: ./tr_pow
La différence est moins grosse, mais quand même toujours dans le bon sens
Partager