Comment optimiser la mémoire [Résolu]

jnmchl
Messages postés
67
Date d'inscription
dimanche 16 octobre 2005
Dernière intervention
13 novembre 2009
- 23 juin 2008 à 21:51 - Dernière réponse : florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 28 juin 2008 à 11:35
Bonjour,
J'ai une application qui semble nécessiter beaucoup de mémoire : je pense celà car chez moi j'ai 1Go de RAM et il tourne sans problème alors que au travail mes collègues qui n'ont que 256 Mo ça rame énormément.
Alors plutôt que d'appeller au secours à tous vents, je me pose quelques questions où vous pourriez me donner votre avis ou conseils.
Voilà ce que j'observe :
* Mon appli fait 1,4 Mo fichier .exe c'est surtout parce qu'il y a beaucoup de form (une quizaine). Ces forms se chargent en mémoire alors que certaines ne sont utilisées que très rarement. Ne peut-on pas économiser cette mémoire en ne chargeant ces forms  en mémoire qu'au moment de leur appel et peut-on restituer la mémoire après fermeture ?
* L'appli utilise beaucoup de tableaux (array) la plupart sont dynamiques et ne servent que ponctuellement, est-ce qu'un setlength(MonTableau,0); suffit à libérer cette mémoire ?
* Si j'en crois le gestionnaire de tâches : plus j'utilise mon appli et plus sa mémoire utilisée augmente : au démarrage : 7Mo puis ça peut monter progressivement jusqu'à 70Mo, si je réduis dans la barre des tâches 500ko seulement, si je réaggrandis je repars à 7Mo, y'a-t-il une fonction qui permette de revenir à 7Mo règulièrement ?

Merci votre aide, et si vous pensez que je peux avoir d'autres gouffres à mémoire, merci d'émettre vos hypothèses. 

Jean-Michel
Afficher la suite 

Votre réponse

7 réponses

Meilleure réponse
florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 24 juin 2008 à 09:51
3
Merci
Salut !

Pour les forms chargées dynamiquement, tu peux les changer dans Projet>Options>Fiches.
Il faut les changer de colonne pour qu'elles ne soient plus crées par Delphi (ça modifie en fait le code du .dpr)
Après, pour t'en servir, tu peux faire :

1: si c'est une fiche modale :
F := TMyModalForm.Create(nil);
try
  F.ShowModal;
  // traitement des données reçues ici
finally
  F.Free;
end;

2: sinon:
F := TMyForm.Create(Application);
F.Show;

et dans TMyForm tu mets dans l'évènement OnClose: Action := caFree;

Pour les tableaux, normalement ça suffit. Tu peux aussi utiliser Finalize(Array).

Pour l'histoire de la variation énorme de la consommation de mémoire: c'est que tu dois allouer pas mal de trucs que tu ne libères pas au moment opportun (voire que tu ne libères pas !).
Exemple commun: les objets GDI comme GetDC qui doit être suivi d'un ReleaseDC,...
De plus si tu réduits dnas la barre des tâches il n'est pa simpossible que Windows transfère la RAM dans la mémoire d'échange sur le disque dur, ce qui te donnerait l'impression que ton application consomme moins alors que ce n'est pas le cas.

Sinon, tu peux utiliser MemCheck (google) pour vérifier qu'a la fermeture de ton application tu n'as pas oublié de libérer des variables, des objets. Si c'est le cas, une inspection minutieuse s'impose !

Voila, tu as déjà la base ici.
A+
Flo

Ressources Delphi, sources, tutoriaux, actu, ...: www.mx-dev.nethttp://te%3C/body

Merci florenth 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 86 internautes ce mois-ci

Commenter la réponse de florenth
cs_christophedlr
Messages postés
257
Date d'inscription
samedi 3 janvier 2004
Dernière intervention
30 mai 2016
- 27 juin 2008 à 17:23
0
Merci
Pour compléter Florenth, pour les variables ce que tu peux faire suivant tes besoins bien sur, c'est en utiliser moins mais plus souvent.

Par exemple, si tu dois lire 4 informations différentes, si tu t'en sert de suite, au lieux d'allouer 4 variables, tu en alloue qu'une puis tu t'en sert, tu libère et alloue (ou realloue au lieu de libérer), puis tu t'en sert de nouveau pour une fois fini les 4 fois, la libérer.

Maintenant cela dépend des besoins, des fois on peut le faire des fois ce serait trop complexe de ne pas en utiliser plusieurs.
Dans le cas où en utiliser qu'une plutôt que plus, cela réduit la mémoire utilisé vu qu'il faut allouer pour une seule, ensuite c'est toi qui alloue la taille requise et qui libère.

Par contre, effectivement comme dit Florenth, faut pas oublier de libérer quand tu t'en sert plus, cela réduit la RAM utilisé.
Je te souhaite de réussir ton optimisation ;)
Commenter la réponse de cs_christophedlr
florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 27 juin 2008 à 17:28
0
Merci
"c'est en utiliser moins mais plus souvent."

Je ne sais pas à quel type de variable tu fais allusion mais j'en profite pour poser une petite question:

procedure Example;
var
  X, Y, FileNumber, TileNumber: Integer;
begin
  for X := 0 to [...] do Bla1(X);
  for Y := 0 to [...] do Bla2(Y);
  for FileNumber := 0 to [...] do Bla3(FileNumber);
  for TileNumber := 0 to [...] do Bla4(TileNumber);
end;

On voit bien que les 4 variables Integer ne servent pas toutes en même temps et qu'on pourrait n'en utiliser qu'une seule.
Est-ce que pour autant il vaut mieux en déclarer une seule ?

Réponse: non !

Car Delphi et son super compilateur remarque très bien qu'on n'utilise X uniquement à la première ligne, etc...
Et il va en réalité allouer une seule variable !

C'es-y pas magique ça ?

Ressources Delphi, sources, tutoriaux, actu, ...: www.mx-dev.nethttp://te%3C/body
Commenter la réponse de florenth
florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 27 juin 2008 à 17:31
0
Merci
Bon, j'ai oublié le point important de l'histoire:

Tout ça fait gagner de la lisibilité au code et limite les bugs.
En effet, quand on écrit TileNumber au lieu de I (nom courant de la variable de boucle) on sait exactement à quoi on fait référence.

Voila, c'était le message du jour.http://www.mx-dev.net
Commenter la réponse de florenth
jnmchl
Messages postés
67
Date d'inscription
dimanche 16 octobre 2005
Dernière intervention
13 novembre 2009
- 28 juin 2008 à 11:02
0
Merci
Merci pour vos réponses qui contribuent et élargisse mon domaine de connaissance.
Je vois en étudiant mon code que j'ai fais des erreurs de jeunesse (bien que je sois encore assez jeune ...).
ex : je déclarais un string qui ne prenait qu'une valeur 'X' ou rien '' : pour fair des tests if s='X' then ... remplacé de fait par un booléen.

A ce sujet, si j'ai un ordre d'idée de la longueur d'une chaine entre 4 et 12 caractères, celà fait-il gagner de la mémoire (et/ou du temps) de déclarer s:string[12]; plutôt que s:string; ? (car sizeof ne me parait pas cohérent).

Mon thème est vaste ... merci pour les contributions.

Jean-Michel
Commenter la réponse de jnmchl
cs_christophedlr
Messages postés
257
Date d'inscription
samedi 3 janvier 2004
Dernière intervention
30 mai 2016
- 28 juin 2008 à 11:14
0
Merci
Pour te répondre je serais tenté de dire que oui, dans certains langages (je sais pas si c'est le cas du Delphi), la variable quand elle est initialisé dans la mémoire, prend moins de place en définissant un nombre de cases maximum que ne rien spécifié, mais je n'en suis pas sur.
Commenter la réponse de cs_christophedlr
florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 28 juin 2008 à 11:35
0
Merci
Mouais, ça dépend.
Les strings, c'est très spécial - ça doit bien être le type le plus difficile à maîtriser.

Pour ma part, je dirai que "string" tout court convient à peu près partout. Sa taille est automatiquement ajustée, les copies (S2 := S1) ne sont que des copies de pointeur, infiniment plus rapide que si S1 et S2 étaient de string[12].

Par contre, si tu sais calculer la taille que doit faire ta chaîne pour lui faire un traitement, il vaut mieux allouer d'un coup la mémoire.

Exemple:
function MyUpperCase(const S: string): string;
var
  I: Integer;
begin
  for I := 1 to Length(S) do
    Result := Result + UpCase(S[I]);
end;

est infiniment plus lent que :
function MyUpperCase(const S: string): string;

var

  I: Integer;

begin
  SetLength(Result, Length(S));

  for I := 1 to Length(S) do

    Result[I] := UpCase(S[I]);

end;
Et c'est logique, car l'opérateur "+" (concaténation de chaînes) est très gourmand en temps et en mémoire ! Mais très pratique aussi dans certaines circonstances.

Bref, faut bien comprendre les rouages internes et surtout, tester et retester...
Commenter la réponse de florenth

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.