[Delphi] Concaténation de chaines et performances... {long}

JWhy

Expert
Je rencontre actuellement dans un des progs que je fais des pbs de performances...

Avec un coup de profiler, j'ai vu que ce qui prenait du temps etait une fonction (faite maison) bien particuliere dans laquelle je dois concaténer tout un tas de chaines et renvoyer le resultat (plusieurs dizaine de Ko) a la fonction appelante...

la boucle principale de la fonction consiste a ajouter au result la valeur de differentes variables plus un saut de ligne (CRLF)...

Bien evidemment, le code est un peu plus complexe, mais en simplifiant a l'extreme, ca donne qqchose comme ca:
Code:
for i:= 0 to count-1 do
  result := result + #13#10 + chaine[i] ;

j'en ai déduit (peut-etre a tort) que ce qui prenait du temps etait la reservation/assignement de la memoire pour les chaines temporaires...


j'ai donc essayé de voir dans un prog. a part les alternatives possibles:
■ utilisation de l'operateur +

en une fois: (nom de code: [g]concat[/g])
Code:
for i:= 0 to count-1 do
  result := result + #13#10 + chaine[i] ;

en 2 fois (nom de code: [g]concat2[/g])
Code:
for i:= 0 to count-1 do
begin
  result := result + #13#10;
  result := result + chaine[i];
end;


■ utilisation de la fonction format (nom de code: [g]format[/g])
Code:
for i:= 0 to count-1 do
  result := format('%s'#13#10'%s', [result,chaine[i]]);

■ assignement de la memoire par bloc de 8k et copie des chaines caracteres par caracteres (nom de code: [g]array[/g])
Code:
aryPos := 0;
setlength(aryResult,8000);
FillChar(aryResult[aryPos], 8000, #0);
for i:= 0 to count-1 do
begin
  sItem := chaine[i];
  for aryIndex := 1 to length(sItem) do
  begin
    aryResult[aryPos] := sItem[aryIndex];
    inc(aryPos);
  end;
end;

■ assignement de la memoire par bloc de 8k et copie des chaines via system.move() (nom de code: [g]move[/g])

Code:
aryPos := 0;
setlength(aryResult,8000);
FillChar(aryResult[aryPos], 8000, #0);
for i:= 0 to count-1 do
begin
  sItem := chaine[i];
  System.Move(sItem[1], aryResult[aryPos],length(sItem));
  aryPos := aryPos + length(sItem);
end;

j'ai donc fait un petit prog pour tester cela et j'ai mesuré le temps pris pour chaques options...
Le source est dispo



voila les resultats que j'obtiens sur un PIV 2.4Ghz, les resultats sont en millisecondes :

Code:
-------------------------------------------------------------
Test avec 1000 boucles
-------------------------------------------------------------
concat : 31
concat2: 0
format : 47
array  : 0
move   : 0

-------------------------------------------------------------
Test avec 5000 boucles
-------------------------------------------------------------
concat : 672
concat2: 0
format : 1609
array  : 0
move   : 0

-------------------------------------------------------------
Test avec 10000 boucles
-------------------------------------------------------------
concat : 2766
concat2: 0
format : 6765
array  : 0
move   : 16

il est clair que le [g]format [/g]n'est pas la solution (on s'en doutait un peu des le debut). on le vire des tests suivant...
le [g]array [/g]et le [g]move [/g]sont rapides, ca ne m'etonne pas...
par contre je ne comprends pas les differences entre le [g]concat [/g]et [g]concat2 [/g]:??:




Code:
-------------------------------------------------------------
Test avec 25000 boucles
-------------------------------------------------------------
concat : 19297
concat2: 16
format : ca va ramer... on passe ce test...!
array  : 0
move   : 94
[g]concat [/g]est au tas (on le vire des prochains tests), [g]move [/g]commence a ralentir
[g]array [/g]semble un poil plus performant que [g]concat2[/g]



Code:
-------------------------------------------------------------
Test avec 50000 boucles
-------------------------------------------------------------
concat : ca va ramer... on passe ce test...!
concat2: 31
format : ca va ramer... on passe ce test...!
array  : 16
move   : 297

-------------------------------------------------------------
Test avec 75000 boucles
-------------------------------------------------------------
concat : ca va ramer... on passe ce test...!
concat2: 47
format : ca va ramer... on passe ce test...!
array  : 31
move   : 515

-------------------------------------------------------------
Test avec 100000 boucles
-------------------------------------------------------------
concat : ca va ramer... on passe ce test...!
concat2: 63
format : ca va ramer... on passe ce test...!
array  : 46
move   : 1016

-------------------------------------------------------------
Test avec 500000 boucles
-------------------------------------------------------------
concat : ca va ramer... on passe ce test...!
concat2: 312
format: ca va ramer... on passe ce test...!
array  : 282
move   : 24328
[g]move [/g]est au tas, [g]array [/g]est toujours plus performant que [g]concat2[/g]



donc au final, on obtiens un classement avec
1. [g]array [/g](copie car. par car.)
2. [g]concat2 [/g](operateur +, une ligne par variable a concatener)
3. [g]move [/g](copie direct en memoire)
4. [g]concat [/g](operateur +, tout sur une ligne)
5. [g]format [/g]

il y a plusieurs choses que je ne comprends pas dans ses resultats (si cette tendance est confirmée par d'autres):
- pourquoi [g]concat [/g]rame par rapport a [g]concat2 [/g]? ca ne devrait etre pas la meme chose au final pour le compilateur ?
- pourquoi [g]array [/g]est plus performant que [g]move [/g]? je pensais que ca aurait donné les memes resultats ou que [g]move [/g]aurait eté plus rapide ?

si qq'un a des des reponses a me donner , je suis preneur !
merci :merci:

JY.
 

daspuner

Nouveau membre
Pour comparer avec un 2500+ Barton
Compilé avec Delphi 5 , tu es en 6 je crois.
-------------------------------------------------------------
Test avec 25000 boucles
-------------------------------------------------------------
concat : 19385
concat2: 10
format : ca va ramer... on passe ce test...!
array : 10
move : 60

-------------------------------------------------------------
Test avec 50000 boucles
-------------------------------------------------------------
concat : ca va ramer... on passe ce test...!
concat2: 20
format : ca va ramer... on passe ce test...!
array : 20
move : 245

Demain si je trouve un moment(au boulot ;) ) je compile Avec D6 au boulot et j'essaie de comprendre.
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 128
Messages
6 717 843
Membres
1 586 372
Dernier membre
Meeithot
Partager cette page
Haut