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 :

RAM non utilisée


Sujet :

Langage Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Juin 2004
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 157
    Par défaut RAM non utilisée
    Bonjour,

    Résumé du problème :

    Je suis confronté a deux problèmes mémoire sur une application delphi.
    1°) une dérive mémoire au cours de l'exécution (je me charge de ce pb)
    2°) l'incapacité, pour mon application à utiliser plus de 230 Mo. (c'est pour ce pb que je sollicite votre analyse)

    Mon contexte informatique est le suivant :

    Windows XP pro SP3 - 2Go de RAM
    Delphi7 Entreprise.

    Description du problème

    Dans mon application j'ai un code de calcul qui dérive en mémoire. Pour bien mettre en évidence le problème j'ai encapsulé ce code dans une boucle de 1000 itérations.

    Situation en début de boucle :
    le processus occupe environ 190 Mo
    environ 670 Mo sont occupés sur le poste

    Situation aprè environ 500 boucles :
    le processus occupe environ 220 Mo
    environ 700 Mo sont occupés sur le poste

    J'obtiens "Runtime erreur, mémoire insuffisante"

    En lançant plusieurs fois la boucle j'obtiens toujours le même résultat, c'est à dire un plantage après environ 500 boucles et 220 Mo occupés par le processus.

    J'ai essayé de changer $MINSTACKSIZE et $MAXSTACKSIZE mais le résultat reste le même sinon très voisin.

    Ma question (enfin ) existe-t-il une limitation intrinsèque aux exécutables produits avec delphi7 ? S'agit-il d'une limitation de XP ?

    Merci de votre (longue) attention

  2. #2
    Membre Expert

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 47
    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
    Par défaut
    Il va être assez difficile de répondre à ton problème sans voir le code et la gestion mémoire effectuée...

    Voici qu'en même quelque éléments :

    Ma question (enfin ) existe-t-il une limitation intrinsèque aux exécutables produits avec delphi7 ? S'agit-il d'une limitation de XP ?
    Oui, en Win32 un processus ne peut pas utiliser plus de 2 Go de RAM, et ce quel que soit la mémoire disponible sur la machine.

    J'obtiens "Runtime erreur, mémoire insuffisante"
    Logiquement, ça signifie que c'est la taille maximal du tas (heap) qui a été atteinte.

    J'ai essayé de changer $MINSTACKSIZE et $MAXSTACKSIZE mais le résultat reste le même sinon très voisin.
    Ces directives servent à déterminer la taille de la pile. A priori, ton problème vient de l'utilisation du tas, donc ne devrait être influencé par ces directives.

    Situation en début de boucle :
    le processus occupe environ 190 Mo
    environ 670 Mo sont occupés sur le poste
    Je ne pense pas qu'il s'agisse d'un bon indicateur.
    Si tu n'as rien d'autre, prend le gestionnaire des tâches Windows et regarde la consommation mémoire du processus.
    Mais attention, par défaut, le gestionnaire des tâches affiche la taille du working-set et non pas la taille de la mémoire utilisée par le processus. Sous XP, il suffit généralement de minimiser l'application pour voir sa consommation mémoire tomber à quelques Ko dans le gestionnaire des tâches...
    Reconfigure le gestionnaire des tâches et demande lui d'afficher une colonne qui s'appelle "taille de la mémoire virtuelle".
    Logiquement, si tu as rencontré une erreur out-of-memory, la taille de la mémoire virtuelle a dû augmenter rapidement pour atteindre les 2 Go. Arrivé à 2 Go (voir moins si la machine ne dispose pas de suffisament de mémoire virtuelle), tu rencontres l'erreur.

    Malgré tout, il faut aussi savoir que contrairement à une idée répendu, il ne suffit pas de faire un Free pour que la mémoire soit rendu à Windows.
    Entre le Create/Free du code, et la mémoire de Windows se trouve le gestionnaire mémoire de Delphi.
    ce dernier alloue des gros blocs mémoires auprès de Windows et les redécoupe pour servir les allocations de l'application.
    La mémoire ne peut être rendu à Windows que lorsque toutes les allocations qui ont été effectuées pour un de ces "gros" blocs mémoire ont été libérée.
    De facto, si la mémoire se fragmente pendant le traitement, il se peut que la mémoire ne soit pas rendue à Windows, alors qu'elle est bien disponible pour servir d'autres allocations.

    Pour faire la chasse aux fuites, je te suggère d'installer FastMM4 et d'activer le mode FullDebug. Il te permettra de trouver rapidement les fuites.

  3. #3
    Membre Expert Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Par défaut
    Citation Envoyé par Franck SORIANO Voir le message
    La mémoire ne peut être rendu à Windows que lorsque toutes les allocations qui ont été effectuées pour un de ces "gros" blocs mémoire ont été libérée.
    De facto, si la mémoire se fragmente pendant le traitement, il se peut que la mémoire ne soit pas rendue à Windows, alors qu'elle est bien disponible pour servir d'autres allocations.
    Ah ouais ?!
    Je croyais que les GetMem géraient en direct la memoire Mais bon, crois-tu que les blocs soient si gros que, malgré les libérations, la mémoire ne soit pas désallouée ? A moins que, au pire des cas, il reste dans chaque bloque réellement alloué au système, il reste un objet qui lock sa libération ! Il y a peut être un processus de remappage de la mémoire pour essayer de libérer des blocks. Si tu as plus de précisions, ca m’intéresse, sinon, je creuserai un peu plus la question de mon coté

  4. #4
    Membre confirmé
    Inscrit en
    Juin 2004
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 157
    Par défaut
    Pour connaître la taille occupée par le processus j'ai utilisé l'API "GetProcessMemoryInfo"
    Je n'ai utilisé le gestionnaire de tâches que pour connaître la mémoire restante, mais je crois devoir passer à des primitives Windows pour avoir des informations plus fiables.

    En ce qui concerne la chasse aux fuites (très dépendante de mon application) je m'y colle en parallèle. Mais ma question était plutôt relative à la non utilisation (apparente ?) d'une grosse partie de la mémoire disponible sur mon ordi (2Go) par mon application qui ne semble pas vouloir (pouvoir ?) en prendre plus de 300Mo !

  5. #5
    Membre Expert Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Par défaut
    pour avoir une vue generale de la memoire utilisée par mon processus, j'utilise process explorer de sysinternals. tu vas dans les proprietes de ton process, onglet "performance graph", et tu vois la memoire utilisée

  6. #6
    Membre Expert
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 704
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 704
    Par défaut
    Intéressant comme outil !

    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. :bug: ___ "http://club.developpez.com/regles/#LIII-A"Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.3 Entreprise - Visual studio 2022
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.7)

  7. #7
    Membre Expert

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 47
    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
    Par défaut
    Citation Envoyé par guillemouze Voir le message
    Ah ouais ?!
    Je croyais que les GetMem géraient en direct la memoire Mais bon, crois-tu que les blocs soient si gros que, malgré les libérations, la mémoire ne soit pas désallouée ? A moins que, au pire des cas, il reste dans chaque bloque réellement alloué au système, il reste un objet qui lock sa libération ! Il y a peut être un processus de remappage de la mémoire pour essayer de libérer des blocks. Si tu as plus de précisions, ca m’intéresse, sinon, je creuserai un peu plus la question de mon coté
    Et non, GetMem n'est pas du tout en direct sur la mémoire...
    Ouvre les sources de l'unité System. Tu as une variable globale (privée) MemoryManager qui est une structure qui contient des pointeurs vers les routines d'allocation du gestionnaire mémoire.
    Tu peux remplacer le gestionnaire mémoire par défaut par le tient en utilisant SetMemoryManager.

    La gestion de la mémoire est une tâche très complexe. C'est d'ailleurs parmi les opérations les plus complexes que réalise une application.
    Allouer de la mémoire pour le système d'exploitation est très compliqué. Il faut gérer la protection pages mémoires d'un processus à l'autre. Il faut gérer la pagination, la virtuallisation (les pointeurs utilisés dans un processus ne contiennent pas des adresses de la mémoire physique)...
    Allouer un bloc mémoire auprès de Windows est une opération très très lente. C'est inenvisageable avec les applis en POO moderne, qui passent leur temps à faire des allocations mémoires de très petites taille.
    C'est pourquoi tu es obligé d'allouer des gros blocs et de les redécouper en interne pour les besoins de l'appli.

    Comme tu l'as dit, s'il reste un objet qui utilise un bloc mémoire plus important, le bloc ne peut pas être rendu à Windows... C'est le problème de la fragmentation. Dans FastMM, un bloc médium représente entre 3 Ko et quelques centaines de Ko. Il suffit d'une seule allocation pour interdire de libérer le bloc.
    De plus, si le bloc est recyclé pour servir les smallblocks, il suffit d'une chaîne de caractère de 1 octets pour vérouiller le bloc complet en mémoire...

    Je suis sous BDS2006. Depuis BDS2006, FastMM est le gestionnaire de mémoire par défaut. Tu peux utiliser GetMemoryManagerState pour obtenir un état des lieux assez précis de l'utilisation de la mémoire faite par l'application.
    Je l'utilise pour faire un calcul précis de la consommation mémoire de mon appli en production, et je trace et enregistre cette consommation en permanence en production.
    Je constate très clairement un taux "d'efficacité" du gestionnaire mémoire qui varie de 30% à 80%. C'est à dire que la mémoire réellement allouée par l'application (la somme des GetMem) représente 30% à 80% de la mémoire que FastMM s'est réservé auprès de Windows...
    Sur les graph que je trace à partir de ces mesures, on voit très clairement la mémoire allouée qui varient très rapidement au rythme des Create et des Free.
    Par contre la mémoire réservée par FastMM (et la mémoire consommée auprès de Windows) varient quasiment pas. De temps en temps, le processus va consommer un peu plus de mémoire. FastMM va se réserver quelques blocs médiums en plus... et lorsque cette mémoire est libérée dans l'application... et bien FastMM la garde qu'en même pour lui...
    Il me fait le coup trois ou quatre fois dans la journée.

    Sinon non, il n'y a pas de processus de remappage des blocs en Win32. FastMM utilise trois stratégies différentes de gestion de la mémoire :
    - Les petites allocations : Il utilise des pools de blocs mémoire préalloués de taille fixe. Les petits blocs sont généralement allouer/libérés très fréquemment. Leur durée de vie est assez réduite. La gestion sous cette forme permet de limiter la fragmentation de la mémoire et facilite la réutilisation des trous...
    - Les allocations moyennes : C'est la gestion classique de la mémoire. FastMM alloue des blocs mémoires de quelques centaines de Ko auprès de Windows. Puis le bloc et découpé en gérant des listes chaînées de blocs alloués et de blocs libres. Le principe étant d'essayer de boucher les trous lors des allocations successives.
    - Les allocations de grandes tailles : Il est rare qu'une appli passe son temps à allouer des blocs mémoire d'1 Mo ou plus (d'un seul bloc). Dans ce cas, FastMM alloue la mémoire directement auprès de Windows.

    Par contre, en .Net, tu as le garbage collector qui gère la mémoire totalement différement : Une appli ne peut faire que des allocations, jamais de désallocation. Donc les allocations sont gérées comme une pile. Chaque fois qu'il faut allouer de la mémoire, il suffit de la prendre immédiatement après le dernier bloc alloué. Les allocations sont ainsi quasiment instantanées.
    Lorsque la collecte se déclenche, le GC identifie une liste de trous, puis il compacte la mémoire en déplacant les objets alloués pour qu'il n'y ait aucun trou.
    De cette façon, avec le GC, la mémoire ne se fragmente pas.

  8. #8
    Membre Expert

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 47
    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
    Par défaut
    Un petit exercice pour le fun :

    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
     
    var
      lst : TStrings;
      i : integer;
      GUID : TGUID;
    begin
      lst := TStringList.Create;
      ShowMessage('Etape 0'); // 3016 Ko.
      for i := 0 to 10000000 do
      begin
        CreateGUID(GUID);
        lst.Add(GUIDToString(GUID));
      end;
      ShowMessage('Etape 1');  // 1 026 948 Ko
      for i := 0 to 10000000 do
      begin
        if i mod 10<>0
        then lst[i] := '';
      end;
      ShowMessage('Etape 2');   // 1 026 940 Ko
      for i := 0 to 10000000 do
      begin
        if i mod 10=0
        then lst[i] := '';
      end;
      ShowMessage('Etape 3'); // 86 880 Ko
      lst.Free;
      ShowMessage('Etape 4'); // 5 624 Ko.
    end;
    L'appli démarre. Lorsque le message Etape 0 s'affiche, elle consomme 3 Mo auprès de Windows.
    On alloue 10 000 000 de chaînes de caractères (je crée des GUID convertis en chaînes pour avoir des chaînes alléatoires différentes).

    A l'étape 1, l'appli consomme 1 Go, c'est le résultat de toutes les allocations précédentes.

    Je libère ensuite 90% des chaînes allouées. On devrait s'attendre à ce que la mémoire soit immédiatement rendue, et donc libérer 90% de la mémoire utilisée.

    Mais lorsqu'on arrive à l'étape 2 (90% des chaînes libérées), l'appli consomme toujours 1 Go de mémoire.

    Je libère alors les 10% de chaînes qui n'ont pas été détruite lors du passage précédent.

    Cette fois à l'étape 3, la consommation mémoire tombe à 86 Mo. On vérifie ainsi que définir les chaînes à vide dans la stringlist libère bien la mémoire.
    Cependant, on n'a récupéré que 90% de la mémoire.

    Lorsqu'on détruit la TStringList, qui n'est pourtant qu'un tableau de 10 000 000 de pointeur à nil, on récupère 80 Mo (alors qu'on aurait dû en récupérer que 40 Mo).

    A la fin du code, on est revenu à la situation initiale. Pourtant l'appli consomme qu'en même 5 Mo au lieu des 3 Mo du départ, sans le moindre memory leak !

    Maintenant si on fait :
    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
     
    var
      lst : TStrings;
      i : integer;
      GUID : TGUID;
    begin
      lst := TStringList.Create;
      ShowMessage('Etape 0'); // 3016 Ko.
      for i := 0 to 10000000 do
      begin
        CreateGUID(GUID);
        lst.Add(GUIDToString(GUID));
      end;
      ShowMessage('Etape 1');  // 1 026 948 Ko
      for i := 0 to 10000000 do
      begin
        if i<9000000
        then lst[i] := '';
      end;
      ShowMessage('Etape 2');   // 180 492 Ko
      for i := 0 to 10000000 do
      begin
        if i>=9000000
        then lst[i] := '';
      end;
      ShowMessage('Etape 3'); // 86 880 Ko
      lst.Free;
      ShowMessage('Etape 4'); // 5 624 Ko.
    end;
    Cette fois ci, au lieu de libérer 90% des chaînes allouées à raison de 9 sur 10, on libère les 9 000 000 de chaînes allouées en premier.
    On remarque que cette fois, arrivé à l'étape 2, l'appli a rendu 80% de la mémoire allouée (alors que précédemment, on gardait tout !).

    On voit ainsi clairement l'effet de la fragmentation de la mémoire...

  9. #9
    Membre Expert Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Par défaut
    Merci pour toutes ces infos Franck, c'est vraiment très intéressant
    Et ton exemple illustre parfaitement le principe.
    Merci beaucoup

  10. #10
    Membre confirmé
    Inscrit en
    Juin 2004
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 157
    Par défaut
    Un petit comparatif sur tous les "instruments" de mesure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        		Gestionnaire de tâches           ProcessExplorer                              PsList                 GetMemoryUsage (Ko)
     
                    Util. Mém       Taille MV        Virtual Size   PrivateBytes   Peak WS        VM        Priv                               
     
    Avant Boucle    4234      	188116           378800  	188116  	202876        378800    188116       10936
     
    Après Boucle    5200      	725400           2036372         725400  	567156        2036372   725400       556348
    La "Virtual Size" de Process Explorer et VM" de PSList sont quand même des informations importantes....

  11. #11
    Membre confirmé
    Inscrit en
    Juin 2004
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 157
    Par défaut
    Petites nouvelles de la mémoire.

    Tout d'abord j'avais une variable string (trace) qui grossissait de 4014 caractères à chaque boucle. En la supprimant et en traçant sur fichier à la place (pour un processus pouvant tourner toute la nuit c'est même mieux) j'arrive à faire 1500 boucles au lieu de 400. Dans ce cas (sans cette variable de trace) l'augmentation de la taille du WorkingSet suit beaucoup mieux la taille de mémoire virtuelle utilisée.


    J'ai tracé également sur fichier certains paramètres récupérés à l'aide de l'API Windows : GlobalMemoryStatus. Sur l'image jointe on peut voir l'évolution de certains paramètres en fonction du nombre de boucles. Il apparaît clairement que la mémoire virtuelle disponible suit une "descente" parabolique contrairement à la mémoire physique qui diminue linéairement. Mais là, et c'est
    désormais bien clair, les 2Go de mémoire physique semblent effectivement utilisés par le processus.

    Vos expériences confirment-elles ces phénomènes ? J'imagine que sur Windows 7 je pourrais faire mes 5000 boucles sans problème...

  12. #12
    Membre Expert Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Par défaut
    Je suis loin d’être un expert en mémoire, mais je pense que l'observation du problème est mal ciblée. Si je ne m'abuse, tes 2Go de RAM n'ont rien a voir dans l'histoire, ce qui te bloque, c'est la limite d'adressage du pointer limité à 2Go en 32bits. Rien ne t’empêche d'avoir 5 process de 1Go alors que tu n'as que 2Go de mémoire physique, l'OS se charge de mettre la mémoire en cache. Par contre, si tu dépasse les 2Go de mémoire virtuelle, alors tu a utilisé toutes les adresses pointables par un pointeur de 4octets, d'ou la mémoire insuffisante. Ou alors, peut-être que la limite mémoire d'un process est limité à Min(MemoirePhysique, ~2Go).

    Je ne suis pas sûr du tout de ce que j'avance, ce ne sont que des suppositions, alors n’hésitez pas a me corriger ou a confirmer mes dires.

  13. #13
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    Citation Envoyé par Négrier Voir le message
    Petites nouvelles de la mémoire.

    Tout d'abord j'avais une variable string (trace) qui grossissait de 4014 caractères à chaque boucle. En la supprimant et en traçant sur fichier à la place (pour un processus pouvant tourner toute la nuit c'est même mieux) j'arrive à faire 1500 boucles au lieu de 400. Dans ce cas (sans cette variable de trace) l'augmentation de la taille du WorkingSet suit beaucoup mieux la taille de mémoire virtuelle utilisée.


    J'ai tracé également sur fichier certains paramètres récupérés à l'aide de l'API Windows : GlobalMemoryStatus. Sur l'image jointe on peut voir l'évolution de certains paramètres en fonction du nombre de boucles. Il apparaît clairement que la mémoire virtuelle disponible suit une "descente" parabolique contrairement à la mémoire physique qui diminue linéairement. Mais là, et c'est
    désormais bien clair, les 2Go de mémoire physique semblent effectivement utilisés par le processus.

    Vos expériences confirment-elles ces phénomènes ? J'imagine que sur Windows 7 je pourrais faire mes 5000 boucles sans problème...
    si tu sais devoir allouer 4014 octets 5000 fois, autant en allouer 20070000 dès le départ, le gestionnaire de mémoire ne s'en portera que mieux.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  14. #14
    Membre Expert Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    si tu sais devoir allouer 4014 octets 5000 fois, autant en allouer 20070000 dès le départ, le gestionnaire de mémoire ne s'en portera que mieux.
    De plus, ca ne fait que 20Mo, on est bien loin des 2Go

  15. #15
    Membre émérite
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Par défaut
    Avec la allocation de string or tableaux dynamique en boucle tu risque la fragmentation de la mémoire... passe directement par pointer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    PHugeString=^THugeString;
    THugeString =array[0..0]of Char;

  16. #16
    Membre confirmé
    Inscrit en
    Juin 2004
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 157
    Par défaut
    Bonsoir Guillemouse : oui effectivement il s'agit bien de "la limite d'adressage du pointer limité à 2Go en 32bits" par processus.

    Effectivement la variable trace n'est qu'un petite partie de la dérive mémoire
    mais rien qu'avec cette correction (redirection de la trace vers un fichier) je passe plus de 1500 pas au lieu de 400 ce qui m'arrange beaucoup

    La correction plus profonde de la dérive mémoire est de bien plus long terme.

    Ceci dit, de connaitre précisément la mémoire consommée (par GlobalMemoryStatus) m'a permis d'arrêter proprement le processus sans avoir une exception. Je fais un test sur le pourcentage de mémoire utilisé et j'arrête si c'est supérieur à 80%

  17. #17
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    Citation Envoyé par guillemouze Voir le message
    De plus, ca ne fait que 20Mo, on est bien loin des 2Go
    si tu alloues tout d'un coup oui,

    sinon tu réalloues à chaque fois un bloc plus grand que le précédent qui ne tient donc pas dans la place libérée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // a = alloué, "-" est libéré
    [aaa]
    [---][aaaaaa]
    [---------][aaaaaaaaa]
    [------------------][aaaaaaaaaaaa]
     
    //au lieu d'avoir
    [aaa.........]
    [aaaaaa......]
    [aaaaaaaaa...]
    [aaaaaaaaaaaa]
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

Discussions similaires

  1. [TUNING] pb non utilisation de l'index
    Par ruthene dans le forum Oracle
    Réponses: 10
    Dernier message: 13/04/2006, 17h02
  2. Javascript : non utilisation du CSS
    Par lafracas dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 12/04/2006, 09h49
  3. [SERVICE INTERACTIF] Form non utilisable apres logoff/logon
    Par Spart64 dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 05/03/2006, 13h32
  4. Installation SP2 + RAM non prise en compte
    Par laure_belette dans le forum Windows XP
    Réponses: 3
    Dernier message: 13/10/2005, 12h46
  5. Réponses: 1
    Dernier message: 28/04/2004, 19h36

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