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

Bases de données Delphi Discussion :

Memory leak et composants TSQLQuery


Sujet :

Bases de données Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti Avatar de Feymann
    Femme Profil pro
    Automaticienne - informaticienne industrielle
    Inscrit en
    Juillet 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Automaticienne - informaticienne industrielle
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2012
    Messages : 27
    Par défaut Memory leak et composants TSQLQuery
    Bonjour,

    Mon problème n'est pas simple à décrire, donc désolée pour la longueur. A l'entreprise où je travaille, nous avons développé une application de supervision sous Delphi qu'on déploie, après personnalisation, chez de nombreux clients. Elle fonctionne bien. Un collègue a dû ajouter à son superviseur des procédures particulières répondant aux besoins de son client. Et cette application, elle a des fuites de mémoire. Comme il n'a pas le temps, j'essaie d'identifier le problème et pallier. Pour cela, j'ai créé une petite application à part où je ne fais que me connecter sur 2 bases de données, et exécuter LA procédure soupçonnée de causer le problème. Et il y a effectivement une augmentation d'utilisation de la mémoire à chaque exécution de la procédure, sans que cela redescende. Dans l'application chez le client tout est transactionnel avec des commits et rollbacks. Dans mon application de test non, mais je ne fais qu'appuyer sur des boutons comme "se connecter" ou "exécuter requête".

    Ce que l'on fait :
    - On se connecte sur 2 bases de données (une SQL Server l'autre Firebird)
    - Dans la procédure problématique :
    On récupère depuis une table de la base SQL des références produits (+ 8000 enregistrements), on remplit avec les données une liste d'objet
    Puis dans une table de la base Firebird on regarde si la référence existe déjà. Si non, on fait un insert, si elle existe, on fait un update

    J'ai réalisé différentes choses pour essayer de trouver le problème:
    - J'ai changé des paramètres de connexion ou autre: pas grand changement
    - J'ai ajouté le ReportMemoryLeaksOnShutdown, mais cela ne me sort rien d'intéressant (un Tstringlist créé pour le memoryleak et un ansistring qui n'a rien à voir avec la procédure)
    - Juste lancer l'application et fermer: aucune augmentation
    - Ne faire que récupérer les références depuis base SQL et créer la liste d'objet (pas d'augmentation d'utilisation de la mémoire, malgré la requête vers la base SQL et liste d'objet bien libérée)
    - Créer les TSQLQuery à la volée ou en composant enfichable (créé à la volée: il y a bizarrement moins d'augmentation de mémoire, mais il y en a quand-même)
    - Mettre la requête directement dans le TSQLQuery.SQL et ne changer que les Param[0]...: plus rapide à exécuter mais la mémoire utilisée augmente beaucoup
    - Faire des freeandnil sur les composants créés à la volée aucun changement
    - Ouvrir le tout et utiliser locate: aucune amélioration
    - Créer une procédure stockée dans Firebird et l'appeler : aucune amélioration

    Pour l'instant j'ai juste trouvé une parade pour libérer de la mémoire que le client exécute 1 fois par jour. Mais c'est du palliatif. Je suis un peu à court d'idées. Soit c'est un problème de version de composant ou il y a vraiment quelque chose que l'on ne voit pas et qui nous crève les yeux?

    Donc comme la liste d'objets ne cause pas d'augmentation de mémoire utilisée, je suppose que le problème est dans les composants TSQLquery/connection et ce qu'on en fait. Si vous aviez des idées, je suis preneuse.

    Voici le code de la requête d'origine qui utilise des composants enfichables (sans le rollback, car comme j'ai dit, normalement c'est transactionnel):

    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
     
    procedure TFenPrincipale.RbouvfermeClick(Sender: TObject);
    Var
      i , IndiceActif : Integer;
    begin
     
     
      Try
        ListeDesReferences := TListeImportReference.Create;
        ListeDesReferences.ownsobjects:=True;
     
        // Recherche de tous les fabricants
        Memsuivi.Lines.Add('Cherche la liste des Références');
     
        //Récupération références depuis base SQL Server
        With ThSQLBBASQL Do
        Begin
          if Active then Close;
          SQL.Clear;
          SQL.Add('Select * from FLISTEREFERENCE ORDER BY NUM');
          Open;
          Memsuivi.Lines.Add('End open SQL Reference');
     
          While not Eof do
          Begin
            if Not ListeDesReferences.TestExisteParCodeSupprNum  (FieldByname('REFERENCE').AsString, FieldByname('SUPPR').Asinteger, FieldByname('NUM').Asinteger, IndiceActif) then
            Begin
              Memsuivi.Lines.Add('Ajoute ' + FieldByname('REFERENCE').AsString);
              FImportReference := TImportReference.Create;
              FImportReference.FReference       := FieldByname('REFERENCE'   ).AsString;
              FImportReference.FDiametre        := FieldByname('DIAMETRE'    ).AsFloat;
              FImportReference.FCodeDate        := FieldByname('CODEDATE'    ).Asinteger;
              FImportReference.FCodeFab         := FieldByname('CODEFAB'     ).Asinteger;
              FImportReference.FrefAMarquer     := FieldByname('REFAMARQUER' ).AsString;
              FImportReference.FRefSecondaire   := FieldByname('REFAMARQUER2').AsString;
              FImportReference.FNomFichier      := FieldByname('NOMDUFICHIER').AsString;
              FImportReference.FSite            := FieldByname('SITE'        ).AsString;
              FImportReference.FNumero          := FieldByname('NUM'         ).Asinteger;
              FImportReference.FSuppression     := FieldByname('SUPPR'       ).Asinteger;
              FImportReference.FDateCreation    := FieldByname('DATECREATION'      ).ASDateTime;
              FImportReference.FDateModification:= FieldByname('DATEMODIFICATION'  ).AsDateTime;
              FImportReference.FEtat            := FieldByname('ETAT'              ).AsInteger;
              FImportReference.FRefComp1        := FieldByname('REFCOMPLEMENTAIRE1').AsString;
              FImportReference.FRefComp2        := FieldByname('REFCOMPLEMENTAIRE2').AsString;
              FImportReference.FRefComp3        := FieldByname('REFCOMPLEMENTAIRE3').AsString;
              FImportReference.FRefComp4        := FieldByname('REFCOMPLEMENTAIRE4').AsString;
              FImportReference.FIncremental     := FieldByname('INCREMENTAL'       ).ASInteger;
              FImportReference.FNbDigits        := FieldByname('NBDIGITS'          ).ASInteger;
              FImportReference.FSite            := 'LAM';
              ListeDesReferences.Add(FImportReference);
            End;
            Next;
          End;
     
          // Début de la transaction
          Try
            Memsuivi.Lines.Add('Mise à jour de la liste des Références');
     
            // Requête d'insertion d'un fabricant
            ThSQLInsertDBBAFB.Close;
            ThSQLInsertDBBAFB.SQLConnection:=ThDBDistantBBAFB;
            ThSQLInsertDBBAFB.SQL.Clear;
            ThSQLInsertDBBAFB.SQL.Add(  ' INSERT INTO FLISTEREFERENCE  (  NUM, REFERENCE, DIAMETRE, CODEDATE, CODEFAB, REFAMARQUER, REFAMARQUER2, SUPPR, SITE, NOMDUFICHIER, DATECREATION, DATEMODIFICATION,ETAT, ');
            ThSQLInsertDBBAFB.SQL.Add(  ' REFCOMPLEMENTAIRE1, REFCOMPLEMENTAIRE2, REFCOMPLEMENTAIRE3, REFCOMPLEMENTAIRE4, INCREMENTAL, NBDIGITS  )');
            ThSQLInsertDBBAFB.SQL.Add(  ' VALUES    (:NUM,:REFERENCE,:DIAMETRE,:CODEDATE,:CODEFAB,:REFAMARQUER,:REFAMARQUER2,:SUPPR,:SITE,:NOMDUFICHIER, :DATECREATION, :DATEMODIFICATION,:ETAT, ');
            ThSQLInsertDBBAFB.SQL.Add(  ' :REFCOMPLEMENTAIRE1, :REFCOMPLEMENTAIRE2, :REFCOMPLEMENTAIRE3, :REFCOMPLEMENTAIRE4,:INCREMENTAL, :NBDIGITS  )');
     
            // Requête de mise à jour du fabricant
            ThSQLUpdateDBBAFB.Close;
            ThSQLUpdateDBBAFB.SQLConnection:=ThDBDistantBBAFB;
            ThSQLUpdateDBBAFB.SQL.Clear;
     
            ThSQLUpdateDBBAFB.SQL.Add( ' UPDATE FLISTEREFERENCE SET REFERENCE=:REFERENCE, DIAMETRE=:DIAMETRE, CODEDATE=:CODEDATE, CODEFAB=:CODEFAB, ');
            ThSQLUpdateDBBAFB.SQL.Add( '  REFAMARQUER=:REFAMARQUER, REFAMARQUER2=:REFAMARQUER2, SUPPR=:SUPPR, SITE=:SITE, NOMDUFICHIER=:NOMFICHIER , DATECREATION=:DATECREATION, DATEMODIFICATION=:DATEMODIFICATION,ETAT=:ETAT,');
            ThSQLUpdateDBBAFB.SQL.Add( ' REFCOMPLEMENTAIRE1=:REFCOMPLEMENTAIRE1, REFCOMPLEMENTAIRE2=:REFCOMPLEMENTAIRE2, REFCOMPLEMENTAIRE3=:REFCOMPLEMENTAIRE3,REFCOMPLEMENTAIRE4=:REFCOMPLEMENTAIRE4,  ');
            ThSQLUpdateDBBAFB.SQL.Add( ' INCREMENTAL=:INCREMENTAL, NBDIGITS=:NBDIGITS       WHERE NUM=:NUM ');
     
     
            ThSQLSelectDBBAFB.Close;
            ThSQLSelectDBBAFB.SQLConnection:=ThDBDistantBBAFB;
            ThSQLSelectDBBAFB.SQL.Text :=   'SELECT REFERENCE,SUPPR, SITE,DATEMODIFICATION,NUM FROM FLISTEREFERENCE WHERE NUM=:NUM '; 
     
     
            for I := 0 to ListeDesReferences.Count - 1 do
            Begin
              // Mise à jour de la liste des fabricants => Tout se fait sur la base distante
              ThSQLSelectDBBAFB.Close;
              ThSQLSelectDBBAFB.Params[0].AsInteger := ListeDesReferences[I].FNumero;
              ThSQLSelectDBBAFB.Open;
              Memsuivi.Lines.Add('Requête '+inttostr(i)+'/'+inttostr(ListeDesReferences.Count - 1));
     
              if ThSQLSelectDBBAFB.IsEmpty then
              Begin
                Memsuivi.Lines.Add('Creation Référénces ' + ListeDesReferences.Items[I]  .FReference);
                ThSQLInsertDBBAFB.Close;
                ThSQLInsertDBBAFB.Params[0 ].Asinteger   :=  ListeDesReferences.Items[I].FNumero;
                ThSQLInsertDBBAFB.Params[1 ].AsString    :=  ListeDesReferences.Items[I].FReference;
                ThSQLInsertDBBAFB.Params[2 ].AsFloat     :=  ListeDesReferences.Items[I].FDiametre;
                ThSQLInsertDBBAFB.Params[3 ].Asinteger   :=  ListeDesReferences.Items[I].FCodeDate;
                ThSQLInsertDBBAFB.Params[4 ].Asinteger   :=  ListeDesReferences.Items[I].FCodeFab;
                ThSQLInsertDBBAFB.Params[5 ].AsString    :=  ListeDesReferences.Items[I].FrefAMarquer;
                ThSQLInsertDBBAFB.Params[6 ].AsString    :=  ListeDesReferences.Items[I].FRefSecondaire;
                ThSQLInsertDBBAFB.Params[7 ].Asinteger   :=  ListeDesReferences.Items[I].FSuppression;
                ThSQLInsertDBBAFB.Params[8 ].AsString    :=  ListeDesReferences.Items[I].FSite;
                ThSQLInsertDBBAFB.Params[9 ].AsString    :=  ListeDesReferences.Items[I].FNomFichier;
                ThSQLInsertDBBAFB.Params[10].AsDateTime  :=  ListeDesReferences.Items[I].FDateCreation;
                ThSQLInsertDBBAFB.Params[11].AsDateTime  :=  ListeDesReferences.Items[I].FDateModification;
                ThSQLInsertDBBAFB.Params[12].AsInteger   :=  ListeDesReferences.Items[I].FEtat;
                ThSQLInsertDBBAFB.Params[13].AsString    :=  ListeDesReferences.Items[I].FRefComp1;
                ThSQLInsertDBBAFB.Params[14].AsString    :=  ListeDesReferences.Items[I].FRefComp2;
                ThSQLInsertDBBAFB.Params[15].AsString    :=  ListeDesReferences.Items[I].FRefComp3;
                ThSQLInsertDBBAFB.Params[16].AsString    :=  ListeDesReferences.Items[I].FRefComp4;
                ThSQLInsertDBBAFB.Params[17].AsInteger   :=  ListeDesReferences.Items[I].FIncremental;
                ThSQLInsertDBBAFB.Params[18].AsInteger   :=  ListeDesReferences.Items[I].FNbDigits;
                ThSQLInsertDBBAFB.ExecSQl;
                ThSQLInsertDBBAFB.Close;
              End
              Else
              Begin
                // Le Numéro existe mais les infos sont différentes => on met à jour
                if (ThSQLSelectDBBAFB.FieldByname('REFERENCE'        ).AsString    <> ListeDesReferences.Items[I].FReference  ) Or
                   (ThSQLSelectDBBAFB.FieldByname('SUPPR'            ).Asinteger   <> ListeDesReferences.Items[I].FSuppression) Or
                   (ThSQLSelectDBBAFB.FieldByname('SITE'             ).AsString    <> ListeDesReferences.Items[I].FSite       ) Or
                   (ABS(ThSQLSelectDBBAFB.FieldByname('DATEMODIFICATION' ).AsDateTime-ListeDesReferences.Items[I].FDateModification )>1/86400)  Then
                Begin
                  Memsuivi.Lines.Add(' Mise à jour de la référence ' + ListeDesReferences.Items[I].FReference);
                  ThSQLUpdateDBBAFB.Close;
     
                  ThSQLUpdateDBBAFB.Params[0 ].AsString    := ListeDesReferences.Items[I].FReference;
                  ThSQLUpdateDBBAFB.Params[1 ].AsFloat     := ListeDesReferences.Items[I].FDiametre;
                  ThSQLUpdateDBBAFB.Params[2 ].Asinteger   := ListeDesReferences.Items[I].FCodeDate;
                  ThSQLUpdateDBBAFB.Params[3 ].Asinteger   := ListeDesReferences.Items[I].FCodeFab;
                  ThSQLUpdateDBBAFB.Params[4 ].AsString    := ListeDesReferences.Items[I].FRefAMarquer;
                  ThSQLUpdateDBBAFB.Params[5 ].AsString    := ListeDesReferences.Items[I].FRefSecondaire;
                  ThSQLUpdateDBBAFB.Params[6 ].AsInteger   := ListeDesReferences.Items[I].FSuppression;
                  ThSQLUpdateDBBAFB.Params[7 ].AsString    := ListeDesReferences.Items[I].FSite;
                  ThSQLUpdateDBBAFB.Params[8 ].AsString    := ListeDesReferences.Items[I].FNomFichier;
                  ThSQLUpdateDBBAFB.Params[9 ].AsDateTime  := ListeDesReferences.Items[I].FDateCreation;
                  ThSQLUpdateDBBAFB.Params[10].AsDateTime  := ListeDesReferences.Items[I].FDateModification;
                  ThSQLUpdateDBBAFB.Params[11].AsInteger   := ListeDesReferences.Items[I].FEtat;
                  ThSQLUpdateDBBAFB.Params[12].AsString    := ListeDesReferences.Items[I].FRefComp1;
                  ThSQLUpdateDBBAFB.Params[13].AsString    := ListeDesReferences.Items[I].FRefComp2;
                  ThSQLUpdateDBBAFB.Params[14].AsString    := ListeDesReferences.Items[I].FRefComp3;
                  ThSQLUpdateDBBAFB.Params[15].AsString    := ListeDesReferences.Items[I].FRefComp4;
                  ThSQLUpdateDBBAFB.Params[16].AsInteger   := ListeDesReferences.Items[I].FIncremental;
                  ThSQLUpdateDBBAFB.Params[17].AsInteger   := ListeDesReferences.Items[I].FNbDigits;
                  ThSQLUpdateDBBAFB.Params[18].AsInteger   := ListeDesReferences.Items[I].FNumero;
                  ThSQLUpdateDBBAFB.ExecSQl;
                  ThSQLUpdateDBBAFB.Close;
                End;
              End;
     
            End;
     
            // Fermeture des Query
            if ThDBDistantBBAFB.InTransaction then ThDBDistantBBAFB.Commit(TransactionDescThDistantBBAFB);
     
            ThSQLSelectDBBAFB.Close;
            ThSQLUpdateDBBAFB.Close;
            ThSQLInsertDBBAFB.Close;
     
          Except
            On e: exception Do
            Begin
              Memsuivi.Lines.Add('EXCEPT-' + e.Message);
            End;
          End;
     
          Close;
        End;
        ListeDesReferences.Clear;
        ListeDesReferences.Free;
        Memsuivi.Lines.Add('Fabricants intégrés');
     
      Except
        On e: exception Do
        Begin
          Memsuivi.Lines.Add('GLOBAL-' + e.Message);
        End;
      End;
     
    end;
    Merci d'avance.

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 635
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    cela me semble plus un problème Delphi que Firebird ! Faut-il que je déplace la discussion dans Delphi/base de données ?

    Purement Firebird je dirais que la seule chose qui m'interpelle c'est :
    Puis dans une table de la base Firebird on regarde si la référence existe déjà. Si non, on fait un insert, si elle existe, on fait un update
    UPDATE OR INSERT https://firebirdsql.org/refdocs/lang...or-insert.html serait envisageable et plus rapide que de rechercher si existe et faire Update ou Insert selon le cas

    Créer une procédure stockée dans Firebird et l'appeler
    étonnant qu'il y ait fuite de mémoire si tout le traitement est dans la procédure stockée

    Partie Delphi
    je n'ai pas l'habitude d'utiliser ce composant TSQLQuery . DBExpress n'est pas ma tasse de thé en fait j'utilise surtout Firedac et parlant de Firedac j'aurai utilisé nombre de ses possibilités (ArrayDML car ce que vous faites y ressemble beaucoup, du LocalSQL ou du BatchMove).

    une chose certaine j'aurai utilisé 2 TSQLQuery différents entre celui de la ligne 79 (le SELECT) (je ne comprends pas les lignes 70 à 76 AMHA inutiles ainsi que la remise systèmatique de ThSQLSelectDBBAFB.SQLConnection:=ThDBDistantBBAFB;) et ceux utilisé pour les UPDATE et INSERT
    Comme je le suggérai j'utiliserai plutôt un seul SQL de type UPDATE OR INSERT et un fois le SQL posé, je ferai un prepare ce qui permettrait très certainement d'améliorer les perfs. Bien évidement cette partie serait en dehors de la boucle.

    Autre point, je ne crois pas qu'il faille des Close dès qu'il s'agit de ExecSQL cela n'ouvre pas d'ensemble de données, mais bon c'est du DBExpress donc pas pour moi

  3. #3
    Membre averti Avatar de Feymann
    Femme Profil pro
    Automaticienne - informaticienne industrielle
    Inscrit en
    Juillet 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Automaticienne - informaticienne industrielle
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2012
    Messages : 27
    Par défaut
    Bonsoir SergioMaster,

    Merci pour votre réponse. On peut probablement déplacer le sujet, j'hésitais moi-même quel forum/sous-forum choisir.

    Mon collègue a créé un composant pour chaque usage: les insert, un pour le select et un pour le update, d'où le code vers les lignes 70... Je ne discutais pas sa façon de faire dans un premier temps. Très intéressant le lien inséré, je vais regarder cela demain.

    Oui, là où je commençais à donner ma langue au chat c'est quand la procédure stockée n'améliorait pas non plus les choses. Toutefois, ma procédure servait seulement à vérifier que la référence existe ou pas et en fonction de cela on remplissait les paramètres des sqlquery pour les inserts ou celui des update. J'aurais peut-être pu faire mieux, mais c'était la première procédure stockée de ma vie... Mais n'empêche que faire une procédure stockée n'a même pas diminué l'ampleur de la fuite.

    Préciser les sqlconnection c'était ajouté au cas-où Delphi se perdrait éventuellement dans ses affectations. Les close, parce qu'on a l'habitude de travailler comme ça.

    Pour information on a Delphi 2010. Déjà récemment on a dû changer nos dll Midas, car ce qu'on avait avant avait un bug dans la détection des modifications dans les tables (avec Applyupdate). Je ne connais pas Firedac, mais d'après le site d'Embarcadero, c'est prometteur.

    Je vais refaire d'autres essais et un autre collègue, qui a XE2, je lui demanderais de voir si cela se comporte pareil.

    Bonne soirée

  4. #4
    Membre émérite
    Homme Profil pro
    Inscrit en
    Février 2006
    Messages
    565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations forums :
    Inscription : Février 2006
    Messages : 565
    Par défaut
    Bonjour.

    En regardant vite fait le code de votre procédure je remarque que FImportReference := TImportReference.Create; n'est jamais détruis avec FImportReference.Destroy. Est-ce normal ? (Mes notions en Delphi sont plus que limitées)

  5. #5
    Membre averti Avatar de Feymann
    Femme Profil pro
    Automaticienne - informaticienne industrielle
    Inscrit en
    Juillet 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Automaticienne - informaticienne industrielle
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2012
    Messages : 27
    Par défaut
    Bonjour,

    Merci pour vos réponses.

    D'après ce que je sais, comme les FImportReference sont ajoutés à une liste, ils appartiennent à la liste et donc ils sont détruits quand on fait ListeDesReferences.Free;
    Memsuivi, c'est moi qui l'ai ajouté pour suivre ce qu'on fait car quand on fait un update sur plus de 8000 enregistrements, c'est assez long. Je ne vois pas pourquoi par ailleurs dans le sens, que pour mes essais je vidais toujours ma table Firebird. Donc soit je ne faisais que des insert soit que des update, sachant que je n'ai rien changé dans les références, donc dans la boucle

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if (ThSQLSelectDBBAFB.FieldByname('REFERENCE'        ).AsString    <> ListeDesReferences.Items[I].FReference  ) Or
                   (ThSQLSelectDBBAFB.FieldByname('SUPPR'            ).Asinteger   <> ListeDesReferences.Items[I].FSuppression) Or
                   (ThSQLSelectDBBAFB.FieldByname('SITE'             ).AsString    <> ListeDesReferences.Items[I].FSite       ) Or
                   (ABS(ThSQLSelectDBBAFB.FieldByname('DATEMODIFICATION' ).AsDateTime-ListeDesReferences.Items[I].FDateModification )>1/86400)  then
    On n'entrait pas dans le "if" donc on ne faisait rien. Alors pourquoi ça augmente ?

    Le Memsuivi,ça peut jouer si je laisse dans le code, mais c'est seulement dans mon application d'essai et je n'exécute la procédure problématique que sur appui sur un bouton. Je vais continuer à creuser, mais je suis à court d'idées.

  6. #6
    Membre averti Avatar de Feymann
    Femme Profil pro
    Automaticienne - informaticienne industrielle
    Inscrit en
    Juillet 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Automaticienne - informaticienne industrielle
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2012
    Messages : 27
    Par défaut
    SergioMaser:

    Actuellement on travaille avec 2.5. On hésite de passer à 3 car plus de possibilités, mais difficile à mettre en place chez nos très nombreux client partout dans le monde.

    Il y a des initialisations et des destroy qui se font ailleurs que dans cette procédure, mais je vais revérifier.*

    Bonne journée.

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    261
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 261
    Par défaut
    Bonjour,

    Citation Envoyé par SergioMaster Voir le message
    Purement Firebird je dirais que la seule chose qui m'interpelle c'est :

    UPDATE OR INSERT https://firebirdsql.org/refdocs/lang...or-insert.html serait envisageable et plus rapide que de rechercher si existe et faire Update ou Insert selon le cas
    Sauf que dans l'application de Feyman, l'update est soumis à certaines conditions. Utiliser update or insert changerait systématiquement la date de modification.
    Comme Fayman ne l'a pas précisé, je suppose que si les 2 serveurs sont externes, les fuites mémoires ne peuvent concerner que l'application Delphi (et la question serait mieux dans le forum Delphi).
    Je me pose plus de questions un peu sur Memsuivi pour lequel je ne vois que des Add() et pas de Clear, mais surtout sur ce ListeDesReferences.
    En cas d'erreur dans la première partie de la procédure il n'est pas libéré. Il serait plus sûr de le libérer dans un bloc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    création
    try
    utilisation
    finally
    libération
    end;
    Ensuite il faudrait s'assurer dans sa définition que le TListeImportReference.Destroy libère bien toute la mémoire.

    André

  8. #8
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 635
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par alanglet Voir le message
    Sauf que dans l'application de Feyman, l'update est soumis à certaines conditions. Utiliser update or insert changerait systématiquement la date de modification.
    J'avoue n'avoir pas tout regardé (fin de journée = inattention) j'ai juste regardé le nombre de paramètres des deux requêtes et vu qu'ils étaient identiques. Maintenant le débat est ouvert
    Citation Envoyé par Feymann
    Pour information on a Delphi 2010.
    maintenant au moins on sait et c'est une bonne chose
    Déjà récemment on a dû changer nos dll Midas, car ce qu'on avait avant avait un bug dans la détection des modifications dans les tables (avec Applyupdate).
    Voilà une des causes de ma désaffection de DBExpress
    Je ne connais pas Firedac, mais d'après le site d'Embarcadero, c'est prometteur.
    je confirme, j'y retrouve tous les ingrédients d'un bon BDE Like (avec D2010 j'utilisais ZEOSDBO) avec de nombreuses fonctionnalités supplémentaires, le seul reproche que l'on pourrait faire c'est que seul le moteur SQLite soit encapsulé, en comparaison AniDAC en encapsule un peu plus.

    Pour ce qui est de FImportReference j'ai zappé tout d'abord parce que j'ai l'habitude d'utiliser les variables Fxxxx comme des propriétés et s'il y a création/destruction je le fais souvent dans les blocs initialization / finalization mais aussi parce que je ne me suis pas occupé du remplissage de liste me focalisant uniquement sur la partie Firebird

    Pour revenir à Firebird il n'a pas été indiqué sa version ? Et ce matin je pensais à une chose : il est possible d'interroger une (ou plus) base distante EXECUTE STATEMENT ON EXTERNAL, bien que je n'ai jamais essayé sur d'autres SGBD que Firebird, je pense tout le travail pourrait se faire dans une procédure stockée (sous réserve que l'on puisse interroger la base source)
    Ajouté dans: 2.5

    Description: Avec ON EXTERNAL DATA SOURCE, l'instruction SQL est exécutée dans une connexion distincte à la même ou à une autre base de données, éventuellement même sur un autre serveur. Si la chaîne de connexion est NULL ou '' (chaîne vide), la clause ON EXTERNAL entière est considérée comme absente et l'instruction est exécutée dans la base de données actuelle.
    c'est la partie en gras qui me fait écrire cela

    Je vais refaire d'autres essais et un autre collègue, qui a XE2, je lui demanderais de voir si cela se comporte pareil.
    AMHA cela ne changera rien

Discussions similaires

  1. [MFC] Thread & memory leaks
    Par Racailloux dans le forum MFC
    Réponses: 7
    Dernier message: 15/03/2005, 12h44
  2. Memory leak en C/C++
    Par Roswell dans le forum Autres éditeurs
    Réponses: 6
    Dernier message: 07/07/2004, 19h41
  3. [MFC] A la chasse au memory leak
    Par Yabo dans le forum MFC
    Réponses: 17
    Dernier message: 27/06/2004, 17h35
  4. Réponses: 7
    Dernier message: 26/02/2004, 09h32

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