mardi 22 novembre 2011

Benchmark

Je testais aujourd'hui les performances d'un nouveau bout de code pour faire de la sérialisation, templaté de partout, le comparant à du vieux code moins générique, mais réputé rapide.

Et je ne comprenais pas pourquoi mon nouveau code, sur un bout tout simple, le calcul de la taille du buffer nécessaire à la sérialisation d'un vecteur de chaînes de caractères, était plus lent. Pour un vecteur de 10000 chaînes, mon code tournait à 19µs, et l'autre à 14µs.

L'algorithme était pourtant tout bête: on prend 4 pour contenir la taille du vecteur, puis on ajoute pour chaque chaîne 4, pour la longueur de la chaine, puis la longueur de la chaîne elle-même. En pseudo-code, pour un vecteur v: 4 + (for each c in v : 4 + length(c)).

Je tente de remplacer mes itérateurs par des entiers et des index, j'enlève et remets les templates, je vérifie bien que le compilo inline tout... Toujours la différence.

Finalement, c'était tout bête. Une telle différence vient rarement des micro-optimisations du code, et bien plus souvent d'un algorithme suboptimal. Le vieux code calculait la longueur de cette manière: 4 + 4 * length(v) + (for each c in v : length(c)). Ce qui sauvait 10000 additions contre une simple multiplication, et me coûtait les 4µs.

1 commentaire:

Socrate a dit…

Surtout que gcc, il va te faire "auhaimegie, multiply by four, totally a two left shift"