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

Delphi Discussion :

Script long à l'execution


Sujet :

Delphi

  1. #1
    Membre à l'essai
    Inscrit en
    Mars 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 39
    Points : 19
    Points
    19
    Par défaut Script long à l'execution
    Bonjour, voila, j'ai créé un script permettant de signer un fichier (c'est en fait un port d'un autre langage). Cependant le script d'origine (en C++), met quelques secondes à s'executer sur un gros fichier, alors que mon script en Delphi en met une trentaine voir plus, sur le même fichier.

    J'aimerais savoir si vous avez une solution pour accelerer la rapidité de ce script.

    Voila la fonction :
    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
     
    procedure TForm4.Sign(map: string);
    var
      F: TfileStream;
      buf: integer;
      sum: integer;
    begin
      if MessageDlg('La signature d''une map peut durer un certain temps, variant de 10secondes à 2minutes selon la puissance des ordinateurs. Durant ce temps, le programme semble inaccessible et buggé. Voulez vous toujours signer la map ?',
        mtConfirmation, [mbYes, mbNo], 0) = mrYes then
        begin
          sum := $00000000;
          F := TFileStream.Create(map, fmOpenReadWrite);
          F.Position := $800;
          while F.Position <> F.size do
            begin
              F.ReadBuffer(buf, SizeOf(integer));
              sum := sum xor buf;
            end;
          F.Position := $2D0;
          F.WriteBuffer(sum, SizeOf(integer));
          F.Free;
        end;
    end;
    Merci de votre aide future.

    A+ et Joyeuses Fêtes ^^ !!!

  2. #2
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 292
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 292
    Points : 1 944
    Points
    1 944
    Par défaut
    On pourrait voir le script en C++?

    La seule piste que je vois est de lire plus d'un entier à la fois et/ou de passer par un autre système que le TFileStram, comme AssignFile, Read (ou ReadBlock) ...

  3. #3
    Membre à l'essai
    Inscrit en
    Mars 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Merci de ta réponse.
    Ayant fait ce script ayant plus d'un an et me remettant juste à ce projet, je ne suis pas sur du source originel. Il me semble que c'est le suivant, et je me suis trompé ce n'était pas du C mais du VisualBasic.
    Code vb : 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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    ' Imports VB = Microsoft.VisualBasic
     
    Public Class Form1
     
     
        Private Sub open_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles open.Click       
     
     
     
            Dim opendialog As New OpenFileDialog
     
            '  Dim we2 = VB.Right$(opendialog.FileName, Len(opendialog.FileName) - InStrRev(opendialog.FileName, ".") + 1)
            ' Dim we = Replace(opendialog.FileName, we2, "")
     
            opendialog.ShowDialog()
     
            'Flux de Lecture
            Dim read As New System.IO.BinaryReader(New System.IO.FileStream(opendialog.FileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.ReadWrite))
            ' Flux d'ecriture
            Dim write As New System.IO.BinaryWriter(New System.IO.FileStream(opendialog.FileName, IO.FileMode.Open, IO.FileAccess.Write, IO.FileShare.ReadWrite))
     
            ' on lit tous les 4 bytes a partir de 2048 et on les Xor
            Dim sig As Int32 = 0
            read.BaseStream.Seek(2048, IO.SeekOrigin.Begin)
            For i As Int32 = 2048 To read.BaseStream.Length - 4 Step 4
                sig = sig Xor read.ReadInt32()
            Next
     
            ' on écrit la signature
            write.BaseStream.Seek(720, IO.SeekOrigin.Begin)
            write.Write(sig)
     
            ' On ferme tout
            read.BaseStream.Close()
            write.BaseStream.Close()
            read.Close()
            write.Close()
     
        End Sub
     
    End Class

    EDIT : Le code ci-dessus n'est pas le bon est ne correspond pas à la fonction de signature de fichier. J'ai donné le code originel en C plus bas sur ce fil.

  4. #4
    Membre régulier

    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 133
    Points : 113
    Points
    113
    Par défaut
    Je ne sais pas si à la compilation, le résultat sera le même, mais en delphi tu peux utiliser with, qui n'existe pas (je crois) en C

    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
      if MessageDlg('La signature d''une map peut durer un certain temps, variant de 10secondes à 2minutes selon la puissance des ordinateurs. Durant ce temps, le programme semble inaccessible et buggé. Voulez vous toujours signer la map ?',
        mtConfirmation, [mbYes, mbNo], 0) = mrYes then
        begin
          sum := $00000000;
          with TFileStream.Create(map, fmOpenReadWrite) do
          begin
            Position := $800;
            while Position <> size do
            begin
              ReadBuffer(buf, SizeOf(integer));
              sum := sum xor buf;
            end;
            Position := $2D0;
            WriteBuffer(sum, SizeOf(integer));
            Free;
          end;
        end;
    si ça se trouve ce petit arrangement n'est que visuel pour le développeur mais donne le même résultat à la compilation ...

  5. #5
    Membre à l'essai
    Inscrit en
    Mars 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Merci, j'ai essayé avec ton script, il marche, cependant, il ne met pas moins de temps.

    En farfouillant bien dans les sauvegarde des sources de mon progs (je viens de les retrouver ^^), j'ai découvert un autre code, semblant un peu plus rapide que le premier, n'utilisant pas de TFileStream.
    Le voici :
    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
    27
    28
    procedure TForm1.Button1Click(Sender: TObject);
    const
      SIGN_START = $800;
      SIG_POS = $2D0;
      INIT_SUM = $00000000;
    var
      F: file;
      buf: integer;
      sum: integer;
      i:integer;
    begin
      i:=0;
      sum := INIT_SUM;
      Assignfile(F, './fichier.ext');
      FileMode := 2;
      Reset(F, 1);
      Seek(F, SIGN_START);
      while not eof(F) do
        begin
          BlockRead(F, buf, sizeof(buf));
          sum := sum xor buf;
          i:=i+1;
        end;
      seek(F,SIG_POS);
      BlockWrite(F, sum, sizeof(buf));
      CloseFile(F);
      label1.caption := inttostr(sum);
    end;

    J'ai également retrouvé le code original en C, (le code que j'ai fourni précédemment en VB ne devait pas vraiment correspondre).

    Voici le code en original en C, commenté par Malatar, dans un topic précédent, où j'avais besoin d'aide pour le convertir :
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    // Définition des constantes
     
    #define SIGN_START 0x800
    #define SIG_POS 0x2d0
    #define INIT_SUM 0x00000000
     
    // fonction principale en C, char argv a l'air d'être comme le paramstr().
     
    int main(int argc, char **argv)
    {
    	FILE *fp; // variable TFileStream
    	int sum, buf; // définition de variables
     
    	if (argc != 2) { // si argc <> 2 alors
    	   printf("Bad args.  should be %s <mapfile>\n", argv[0]); // affchage si <> 2
    	   exit(0); // sortir de la fonction
    	}
     
    	if (!(fp = fopen(argv[1], "r+"))) { // ouverture du TFileStream
    	   printf("Error opening file.\n");
    	   exit(0);
    	}
     
    	// initialize xor sum
    	sum = INIT_SUM;
     
    	// go to start of hash
    	fseek(fp, SIGN_START, SEEK_SET);// se positionner dans le fichier (utiliser Seek)
     
    	// assuming 4 byte ints.
    	while (!feof(fp)) { // boucle de récupération des données jusqu'à qu'on arrive en fin de fichier
    	   fread(&buf, sizeof(int), 1, fp); // Utiliser ReadBuffer pour la lecture dans le fichier
    	   sum = sum ^ buf; 
    	}
    	sum = sum ^ buf;
     
    // Ecrit la somme a la position SIG_POS dans le fichier
    	clearerr(fp);
    	fseek(fp, SIG_POS, SEEK_SET);
    	fwrite(&sum, sizeof(int), 1, fp);
    	fclose(fp); // fermeture du fichier
    }

    Si vous avez d'autre idées ...

  6. #6
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 292
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 292
    Points : 1 944
    Points
    1 944
    Par défaut
    J'aurais fait le même code avec AssignFile, donc je ne vois pas comment faire plus rapide (à part peut-être lire plusieurs entiers en même temps, du coup moins d'accès disque ... mais bon, il faut que le nombre soit suffisant).

  7. #7
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    La différence de temps entre C et Delphi réside ici dans le fait que tu fais appel à des méthodes virtuelles la plupart du temps, alors que le C accède directement aux routines originales.

    Certes, les méthodes virtuelles sont à accès indicé, donc en temps constant. Seulement, cela nécessite tout de même trois instructions machines, alors qu'une routine statique n'en prend qu'une. Dans la mesure où tes appels de méthodes sont ce qui couvre la plupart de ton code, cela multiplie par trois ton temps d'exécution... Sans parler de tout ce qui se trouve à l'intérieur de ces méthodes.

    Donc pour gagner du temps, tu peux utiliser les routines de bases de SysUtils.

    Cependant, ce qui serait beaucoup plus efficace, ce serait de lire dans le fichier par blocs de 1Ko, ou plus. En effet, lire 1Ko sur le disque demande à peu près autant de temps que lire 4 octets, car on lit tout en un passage de tête de lecture de disque.
    Cependant, si on lit 4 octets, puis qu'on fait un traitement, avant de relire 4 octets... En attendant la tête de disque est déjà plus loin, et pour lire les 4 octets suivants il faudra attendre qu'elle retrouve la bonne place...

    Essaie donc avec des buffers de 1024 octets, je te garantis que tu vas sentir la différence

  8. #8
    Membre à l'essai
    Inscrit en
    Mars 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Je vais essayer de me documenter sur asignfile, mais sinon, comment pourrais-je lire plusieurs entiers à la fois ?

  9. #9
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Modifie le passage comme suit :
    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
    procedure ...;
    const
      BufSize = 1024;
    var ...;
        Buffer : array[0..BufSize-1] of integer;
        BufCount, I : integer;
    begin
      ...
      F.Position := $800;
      while F.Position < F.Size do
      begin
        BufCount := F.Read(Buffer, BufSize * SizeOf(integer)) div SizeOf(integer);
        for I := 0 to BufCount-1 do
          sum := sum xor Buffer[i];
      end;
      ...
    end;
    En augmentant la valeur de BufSize, tu peux encore accélérer, mais la différence se fera moins sentir... Et gare à la mémoire

  10. #10
    Membre à l'essai
    Inscrit en
    Mars 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Désolé, je n'avais pas vu ton message précédent, je postais le mien en même temps !

    J'ai essayé ton code, c'est miraculeux, sur un fichier de 50mo, ça met même pas une seconde à s'exécuter , contre 50seconde pour l'ancien, merci beaucoup ^^ !!!

  11. #11
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 292
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 292
    Points : 1 944
    Points
    1 944
    Par défaut
    Il faut que je sois plus clair dans mes messages.

    Le code de sjrd est celui auquel je pensais.

  12. #12
    Membre à l'essai
    Inscrit en
    Mars 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    lol, okok, mais aussi, je suis pas bien chaud là, ça fait seulement trois jours que je me suis remis a delphi, donc, je capte pas instantanément !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. script shell pour execution tache de fond mysql
    Par boubourse92 dans le forum Linux
    Réponses: 2
    Dernier message: 09/04/2008, 18h54
  2. recuperer pid d'un script batch en execution
    Par grandtix dans le forum Windows XP
    Réponses: 2
    Dernier message: 24/07/2007, 19h18
  3. Réponses: 5
    Dernier message: 20/07/2006, 02h17
  4. Réponses: 4
    Dernier message: 06/06/2006, 13h27
  5. Réponses: 4
    Dernier message: 21/04/2006, 15h08

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