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 :

Utilisation mémoire de Delphi


Sujet :

Langage Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    177
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 177
    Points : 130
    Points
    130
    Par défaut Utilisation mémoire de Delphi
    Voila, je suis en charge de corriger un serveur écrit de delphi, j'ai supprimé les fuites mémoires mais le serveur ne rend pas toute la mémoire qu'il a prit. il commence à 7 k et après quelques opérations il double. En gros par opération il se garde la moitié de la mémoire qu'il s'est alloué.

    Est ce "normal" (delphi se garde une petite réserve?) ?

  2. #2
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 310
    Points
    2 310
    Par défaut
    Personnellement sans le code je n'y vois pas grand chose.
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  3. #3
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Ha la gestion de la mémoire... un grand sujet en soit...

    Bon pour commencer quelle version de Delphi est-ce que tu utilises ?
    Delphi a changé de gestionnaire mémoire a partir de BDS2006.

    Ensuite il y a de nombreux paramètres à prendre en compte :
    1. Comment fait-tu pour contrôler la mémoire utilisée par ton appli ? Sache que la colonne "Util. mémoire" du gestionnaire de tâche n'est absolument pas révélatrice. Il s'agit de la taille du Working Set de ton appli et pas la taille de l'appli.
    2. Ensuite, Oui "delphi se garde une petite réserve", et même une grosse voir parfois une très grosse.

    7 Ko au démarrage ! personnellement je n'ai jamais vu une appli Delphi utiliser aussi peu de mémoire. Rien d'étonnant a ce que ça augmente très vite.

    Les applis n'allouent pas la mémoire directement auprès de l'OS, mais passent par un gestionnaire de mémoire.
    Ce dernier alloue des "gros" blocs mémoires à l'OS, puis les redécoupe pour servir les demandes de l'appli.
    Lorsque tu libères la mémoire, tu la libère dans le gestionnaire de mémoire. Mais tant que le bloc mémoire alloué à l'OS n'est pas entièrement libéré, le gestionnaire mémoire ne la rendra pas à l'OS.

    C'est ce qui conduit à la fragmentation de la mémoire, qui fait que au final que ton appli consomme beaucoup plus de mémoire auprès de l'OS que ce qu'elle en a réellement besoin.
    J'ai déjà vu une appli s'allouer 120 Mo dans l'OS alors qu'elle en utilisait moins de 20.

    Pour une appli serveur, il faut regarder si la consommation mémoire augmente au cours du temps lorsque le serveur est chargé.
    Une autre solution consiste à instrumenter le gestionnaire mémoire pour qu'il te dise qu'elle est la quantité de mémoire allouée et la quantité réservée.

    Sinon pour les fuites mémoires, il faut faire la chasse au memory leak bien sûr, mais aussi aux libérations tardives (lorsqu'on conserve un bloc mémoire alors qu'on n'en a plus besoin).
    Ces dernières sont très difficiles à repérer et corriger car techniquement ce ne sont pas des fuites mémoires, donc aucun outil ne les repère !
    En particulier avec Delphi, on a souvent le piège du Owner : On crée un composant lorsqu'on en a besoin, en lui définissant un Owner pour qu'il soit détruit automatiquement avec son propriétaire.
    Sauf que si le propriétaire n'est pas détruit ou n'est détruit que très tardivement, on explose vite la consommation mémoire...

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    177
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 177
    Points : 130
    Points
    130
    Par défaut
    J'utilise la version 2006 entreprise. Et oui j'ai regardé la colonne utils. mémoire.

    La charge augmente jusqu'à ce que l'application pète (avant que j'arrive c'était toutes les heures(utilisé par une 15aine de personnes).

    Les 7 Ko c'est parce qu'il n'y a presque rien à charger une 10aine de label et une pool de connexion à la base de donnée.

    Je ne pense pas que je puisse réduire énormément la durée de vie des variables.

    Comment on fait pour voir la vrai consommation d'une appli?

    Est ce qu'il y a un moyen pour qu'il alloue des blocs plus petits (même si on lui donne plus de travail a faire)?

  5. #5
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 289
    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 289
    Points : 1 940
    Points
    1 940
    Par défaut
    La taille de la mémoire virtuelle est aussi à afficher dans le gestionnaire des tâches. Pour la calcul total, je pense que c'est la somme des deux, mais je n'en suis pas sûr du tout.
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2022

  6. #6
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Citation Envoyé par Linkin
    Pour la calcul total, je pense que c'est la somme des deux, mais je n'en suis pas sûr du tout.
    C'est une question que je me pose encore !

    La taille de la mémoire virtuelle correspond à la mémoire réservée dans l'espace d'adressage de l'application. Donc toute la mémoire allouée par l'application se trouve dans cette dernière.

    Mais ensuite, une partie de la mémoire virtuelle sera présente en mémoire physique : c'est le working set.
    Pour rendre les choses un peu plus complexes, les segments mémoires identiques (de la mémoire virtuelle) entre deux applications (par exemple, si on lance l'appli deux fois, le code est présent dans l'espace d'adressage virtuel de chaque appli, donc présent deux fois) peuvent être mappé sur le même segment physique (c'est comme ça que le code n'est finalement réellement présent qu'une fois).

    Donc en principe, le working set est une copie d'une partie de la mémoire virtuelle. Et la mémoire virtuelle qui ne fait pas partie du working set peut être swappée non pas sur disque (enfin si mais ce n'est pas le propos) mais dans le cache système en mémoire physique, qui se trouve au delà de la limite d'adressage à 2 Go par process (ou 3 Go, selon le mode de démarrage de Windows 32 bits).

    Maintenant il y a des fois ou le working set est plus grand que la mémoire virtuelle du process, et ça je ne me l'explique pas !

    Donc je dirais qu'il faut regarder chaque notion en fonction de l'objectif. Pour la chasse aux fuites mémoire, il doit suffir de regarder l'évolution de la consommation de la mémoire virtuelle.

    Pour dimensionner un serveur, il faut peut-être regarder la somme des deux, voir chercher quelle est la taille du working set qu'on peut affecter à chaque appli...

    Citation Envoyé par Arsenic68
    J'utilise la version 2006 entreprise.
    Donc tu utilises FastMM.

    Dans FastMM (dans l'unité System en fait), tu as une fonction GetMemoryManagerState. Cette dernière te permettra d'obtenir une structure TMemoryManagerState qui décrit le nombre de blocs alloués, la taille des allocations, et l'espace réellement utilisé.
    Il faut comprendre un peu le fonctionnement de FastMM, surtout par rapport aux smallblock, MediumBlock et LargeBlock.
    Il faut faire la somme de tout ça pour connaitre l'état d'utilisation de la mémoire.

    ...et une pool de connexion à la base de donnée.
    Tu utilises quels composants pour la connexion à la base ?

    Ce que tu décris ressemble quand même fortement à un memory leak. Mais si tu travailles avec ADO par exemple, ces derniers utilisent le gestionnaire de mémoire COM, qui est invisible pour FastMM (et pour sa détection des memory leak).

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    177
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 177
    Points : 130
    Points
    130
    Par défaut
    J'utilise des TAdoQuery et la pool c'est une TList

    Memcheck ne trouve aucune fuite de mémoire

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 522
    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 522
    Points : 25 052
    Points
    25 052
    Par défaut
    Je suppose que chaque objet créé via Create, utilisé, est à un certain moment libéré par Free ...
    Idem pour les requêtes, un Open consomme de la mémoire, en particulier la tampon des enregistrements, une fois les données lues, un Close libère de la mémoire, et si l'objet n'est vraiment plus utile on en revient au Free

    Tu as vérifié aussi que tous GetMem, New sont bien accompagnés à un moment avec un FreeMem, Dispose, ....
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Citation Envoyé par Arsenic68 Voir le message
    J'utilise des TAdoQuery et la pool c'est une TList

    Memcheck ne trouve aucune fuite de mémoire
    Oublie memcheck. Dans BDS2006, FastMM dispose de son propre détecteur de memory leak.

    Quelque part dans ton projet, il suffit de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ReportMemoryLeaksOnShutdown := true;
    Au moment de la fermeture de ton appli, FastMM t'affichera une liste de tous les blocs mémoire qui n'avaient pas été libérés.

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    177
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 177
    Points : 130
    Points
    130
    Par défaut
    j'ai essayé de le faire sur un autre projet et j'obtiens un truc totalement inexplotable

    1-20 1x ansiString
    20-40 1x AnsiString...

    J'ai essayé de le lancer en modu fulldebugInfo et LogMemoryLeakDetailToFile mais ça me provoque une violation d'accès à la fermeture (et donc pas de joli petit rapport) (J'ai bien coché TD32 et map detaillée)

  11. #11
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    j'ai essayé de le faire sur un autre projet et j'obtiens un truc totalement inexplotable

    1-20 1x ansiString
    20-40 1x AnsiString...
    Ben si, ce résumé rapide te dit qu'il y a des memory leak dans ton appli. Et il t'indique également le type d'objet qui utilise les blocs mémoires non libéré.

    Si tu n'as que des string dans le rapport, ce n'est pas grave. C'est la gestion des strings de Delphi qui fait ça.
    Je te conseille de repérer les objets de plus haut niveau possible qui apparaissent dans le rapport et de chercher où ils sont instanciés et s'ils sont bien détruit.
    En général, ce sont d'abords eux qui génèrent les leaks plus petit.

    De même, si le rapport te sort une liste de medium blocs, ou large bloc c'est que tu as des GetMem, ou des New qui n'ont pas de Freemem, Dispose correspondant.

    J'ai essayé de le lancer en modu fulldebugInfo et LogMemoryLeakDetailToFile mais ça me provoque une violation d'accès à la fermeture (et donc pas de joli petit rapport) (J'ai bien coché TD32 et map detaillée)
    Donc tu as téléchargé et mis en place FastMM4 pour bénéficier de toutes les fonctionnalités de debug de FastMM.
    Si tu as un AV à la fermeture, je vois deux causes possibles :
    - Pour utiliser le mode FullDebug, tu dois compiler une DLL (désolé je ne me souviens plus du nom) qui t'es fournie avec FastMM4 et la placer dans le même répertoire que ton appli. C'est elle qui génère le Log détaillé. Si elle est absente, il n'est pas impossible que ça fasse un AV.
    - Une autre possibilité, c'est que en mode Debug, FastMM4 fait une gestion un peu spéciale de la mémoire pour faire apparaitre les problèmes d'allocations du genre : "je continue à utiliser un objet qui a pourtant été détruit". En temps normal, ça peut fonctionner tant que la mémoire libérée n'est pas réutilisée ou qu'elle n'a pas été rendu à l'OS. Mais FastMM modifie la valeur du pointeur et de la zone pointée pour que ça provoque un AV si tu continue à utiliser l'objet détruit. C'est peut-être la cause de ton AV.

    Pour info, le rapport qu'il est censé te générer comprend une première partie "résumé" qui contient exactement ce que Delphi t'affiche avec ReportMemoryLeaksOnShutdown. Et une partie détaillée qui contient la pile d'appel qui a conduit à l'allocation de chaque bloc mémoire qui n'a pas été libéré.
    C'est très détaillé (voir trop) et avec ça, tu peux corriger très facilement tous les memory leak de l'appli.

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    177
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 177
    Points : 130
    Points
    130
    Par défaut
    j'ai pris celle qui était dans FastMM4\FullDebugMode DLL\Precompiled

    La dll s'apelle FastMM_FullDebugMode.dll

  13. #13
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Ha, elle est livrée précompilée... Je ne m'en souvenais pas. Faut dire aussi que nous on l'avait modifiée pour filtrer un peu le log généré...

    Bon, ça devrait fonctionner alors. Essaie déjà avec un projet de test plus petit.

Discussions similaires

  1. Utilisation partagée de Delphi 2005
    Par Annie BADEY dans le forum EDI
    Réponses: 1
    Dernier message: 16/12/2005, 17h08
  2. Comment utiliser Word avec Delphi 7 ?
    Par muquet dans le forum Débuter
    Réponses: 9
    Dernier message: 06/12/2005, 18h52
  3. [Tomcat][Spring] Problème utilisation mémoire
    Par Wutintin dans le forum Hibernate
    Réponses: 12
    Dernier message: 08/09/2005, 14h57
  4. [MFC] Utilisation mémoire
    Par CTux dans le forum MFC
    Réponses: 10
    Dernier message: 08/07/2005, 09h58
  5. Utilisation Mémoire d'une application
    Par scorplex dans le forum Composants VCL
    Réponses: 8
    Dernier message: 21/05/2005, 03h01

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