IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Text.Write : vitesse d'exécution en Delphi 5 / Delphi 2006


Sujet :

Langage Delphi

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 42
    Points : 19
    Points
    19
    Par défaut Text.Write : vitesse d'exécution en Delphi 5 / Delphi 2006
    Bonjour !

    J'ai constaté un problème de vitesse d'exécution assez gênant avec la méthode Text.Write en Delphi 2006, en particulier sur des fichiers distants (réseau local).

    Par exemple, avec le code suivant ("F" est un fichier text, "Line" une chaine d'environ 200 caractères) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      AssignFile(F, FileName);
      try
        Rewrite(F);
        for l := 1 to 100 do
          begin
            for c := 1 to Length(Line) do
              Write(F, Line[c]);
            Writeln(F);
          end;
      finally
        CloseFile(F);
      end;
    Exécuté sur un fichier distant :
    Delphi 5 -> 0.08 secondes
    Delphi 2006 -> près de 8 secondes

    Il y a-t-il une raison à ça ?

    D'avance merci
    Adrien

  2. #2
    Membre à l'essai
    Inscrit en
    Juin 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 16
    Points : 13
    Points
    13
    Par défaut cela ressemble a un flush automatique
    Je n'ai pas D2006 mais ce que tu decris ressemble a un flush automatique lors d'un appel a WriteLn.
    As-tu regarde de ce cote la ?

    Tu peux aussi reduire le nombre d'appel a WriteLn en construisant une chaine temporaire et en n'appelant writeln que de temps en temps toutes les 10000 lignes par exemple.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 42
    Points : 19
    Points
    19
    Par défaut
    Bonjour

    En fait c'est même à chaque Write (le même code sans les Writeln engendre le même problème).

    D'après Peter Below (TeamB) :
    - à partir de Delphi 2005 ou 2006 (à vérifier), Borland a modifié ses mécanismes de lecture/écriture des fichiers texte, de façon à éviter les pertes en cas de plantage d'une application (plus de cache, on écrit en continu) ;
    - pour les fichiers locaux, le problème est plus ou moins compensé par l'OS qui utilise son propre cache pendant les écritures - ce n'est pas le cas pour les fichiers distants, et le temps d'exécution s'en ressent immédiatement ;
    - il n'existe pas de directive de compilation ou propriété du TApplication pour revenir au mécanisme d'écriture pré Delphi 2005/2006.

    Pour lui la solution est de gérer soi-même le cache (valable pour les fichiers texte, pour le reste je ne sais pas).

    La fonction qui gère le buffer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Function DevOut( Var F: TTextRec ): Integer;
    Begin { DevOut }
      Result := 0;
      With F Do
        If BufPos > (BufSize * 9 div 10) Then
          Begin
            if FileWrite(F.Handle, BufPtr^, BufPos) < 0 then
              Result := GetLastError;
            BufPos := 0;
          End; { If }
    End; { DevOut }
    Après chaque AssignFile :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    var
      F: Text;
      FileName: string;
      Buffer: array [1..$10000] of Byte;
    begin
      ...
      AssignFile(F, FileName);
      SetTextBuf(F, Buffer);
      ...
    end;
    Après chaque Rewrite, Reset...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var
      F: Text;
    begin
      ...
      Rewrite(F);
      TTextRec(F).FlushFunc := TTextRec(F).InOutFunc;
      TTextRec(F).InOutFunc := @DevOut;
      ...
    end;
    ...Ce qui fonctionne effectivement parfaitement.
    Si quelqu'un a une solution moins couteuse en moulinage de code et tests, je reste preneur

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 262
    Points
    25 262
    Par défaut
    C'est assez rigolo, qu'en Delphi 2006, ils ont forcé le Flush, cela troublait beaucoup de monde que les fichiers écrit via Write n'était pas immédiat ... voir le sujet "Forcer Windows à effectuer le writeln complet ?" où le Flush n'était lancé que lorsque le buffer d'écriture était plein ... ce qui est assez troublant ...

    Pour ma part, j''ai plus souvent utiliser BlockWrite ou TFileStream, car justement, j'ai toujours préféré ces fonctions sans tampon ...

    Maintenant, je n'ai que rarement eu besoin d'écrire directement sur un fichier en réseau (je passais plus par du FTP (ou SFTP) ou par une tambouille maison par TCP\IP avec un pool de buffer et un thread différent pour la reception socket et l'écriture fichier)

    BoBoToTo, tu pourrais de faire une classe TFileBufferedStream par exemple qui reprendrais tout le code que tu as imaginé pour redéfinir les fonctions IO, et l'utiliser ensuite ...

    Tu pourrais aussi faire cette classe en héritant un TMemoryStream, ... il existe un tutoriel sur le TStream sur Dev, je ne sais plus où, il y avait toute la démarche à suivre pour faire un TFileBucketStream ...

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 42
    Points : 19
    Points
    19
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    BoBoToTo, tu pourrais de faire une classe TFileBufferedStream par exemple qui reprendrais tout le code que tu as imaginé pour redéfinir les fonctions IO, et l'utiliser ensuite ...
    Je vais probablement partir dans cette direction, c'est ce qui sera le moins couteux pour moi en modifications de code (ça impacte pas mal d'unités plutôt copieuses).

    Dommage cependant que Borland ait fait ce choix sans permettre à ceux qui en avaient besoin de continuer à utiliser un cache... (buffer, flush... tout est encore déclaré dans Delphi 2006, mais court-circuité... inutilisable sans les bidouilles ci-dessus...)

    Merci pour vos réponse

Discussions similaires

  1. Réponses: 3
    Dernier message: 08/09/2008, 07h32
  2. [SQL]ADODataset et ADOQuery Vitesse d'exécution.
    Par aityahia dans le forum Bases de données
    Réponses: 1
    Dernier message: 30/06/2008, 19h44
  3. Exécuter un .exe sans Delphi
    Par Tomimie dans le forum Delphi
    Réponses: 11
    Dernier message: 01/06/2007, 11h42
  4. Au sujet de la vitesse d'exécution des programmes
    Par emie31 dans le forum Langage
    Réponses: 5
    Dernier message: 09/11/2006, 13h42
  5. Réponses: 4
    Dernier message: 02/04/2006, 18h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo