Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Bonjour à tous,
Au sein de ma boite nous venons de livrer une nouvelle version de notre application.
On nous fait remarquer quelques lenteurs qui sont identifiés sur une 10 aines de postes alors que aucun n'est relevé sur les 200 autres.
Sur ces postes, la mémoire se charge d'un coup au lancement de l'application sans aucune explication... Cela varrie, 200Mo sur certains, 700 sur d'autres et jusqu'à 1.7GO sur un poste !
Notre nouvelle version englobe un gros projets pour lequel nous avons :
- migré de PB9 à PB11.5
- utilisé une connexion endriver SQL server natif plutôt que l'ODBC
- utilisé un OCX Foxit Reader pour pouvoir lire des PDF dans l'appli
- revu notre navigation dans l'appli via de images comme boutons dont toutes les GIF ou PNG sont inclues dans le PBR
On recherche aujourd'hui la cause de ce chargement mémoire... Si jamais certains d'entre vous ont éprouvé ce genre de problème nous sommes prenneurs de toute idée ou piste.
Alexis
Dernière modification par Garth (11-08-2011 12:23:41)
Hors ligne
Cela peut provenir des objets non détruit dans un process réccurent, ce qui peut faire gonfler la mémoire considérablement si
les objets générés consomment beaucoup de ressources (souvent des datastores ou datawindows généralement)
Nous avons déjà rencontré ce genre de problèmes que nous avions corrigé temporairement en utilisant la fonction GarbageCollect( ) qui provoque la destructions des objets en mémoires qui ne sont plus utilisés.
Le plus difficile est de localiser le process qui provoque ce gonflement de mémoire...
A+
Vincent
Hors ligne
vince.janssens a écrit:
Le plus difficile est de localiser le process qui provoque ce gonflement de mémoire...
Avez vous des trucs et astuces pour identifier les process ?
C'est dommage que rien n'existe dans PB pour savoir ce que consomme chaque objet de l'appli en mémoire
Hors ligne
Garth a écrit:
Avez vous des trucs et astuces pour identifier les process ?
Exécuter le programme pas à pas et observer l'évolution de la mémoire utilisée dans le gestionnaire de tâches.
Hors ligne
C'est ce qu'on a cherché à faire... sans grand succés
Hors ligne
Le même problème chez nous était lié à la création/destruction d'un nombre très important de datastores... la mémoire n'étant pas complètement libérée par PB à chaque destruction, elle gonfle anormalement.
Vous n'auriez pas des boucles dans lesquelles des datastores sont créés puis détruits (ou même pas détruits du tout !) ?
Hors ligne
J'ai effectivement des boucles avec des DS créés dedans...
Mais ce ne sont pas des DS stockant des tonnes de données.
Pour le coup vous aviez remplacé les DS par quoi ?
Merci de votre réponse.
Hors ligne
Essaye de limiter le nb de DS, par exemple ne pas les créer à chaque passage dans la boucle mais les créer hors de la boucle et les réinitialiser à chaque passage dans la boucle.
Hors ligne
Garth a écrit:
J'ai effectivement des boucles avec des DS créés dedans...
Mais ce ne sont pas des DS stockant des tonnes de données.
Pour le coup vous aviez remplacé les DS par quoi ?
erasorz a écrit:
Essaye de limiter le nb de DS, par exemple ne pas les créer à chaque passage dans la boucle mais les créer hors de la boucle et les réinitialiser à chaque passage dans la boucle.
C'est exactement ce qu'on a fait, et ça a résolu le problème... le nombre de lignes dans le datastore n'empêchera pas l'accumulation de mémoire prise à chaque destruction.
Hors ligne
Bonjour,
J'ai également remarqué qu'une datastore passé en argument d'une méthode ou d'une fonction par valeur augmente la mémoire occupée puisque les données sont dupliquées (logique).
Mais, cette mémoire n'est pas correctement libérée en sortie de fonctions (PB 11.2).
S'il n'y a pas d'impacts (datastore utilisée en lecture par exemple), il est préférable de passer par référence les datastores. Cette petite modification dans notre application a eu une large impact sur la mémoire occupée surtout lorsqu'un large volume de données est concernée.
Hors ligne
buck a écrit:
Bonjour,
J'ai également remarqué qu'une datastore passé en argument d'une méthode ou d'une fonction par valeur augmente la mémoire occupée puisque les données sont dupliquées (logique).
Mais, cette mémoire n'est pas correctement libérée en sortie de fonctions (PB 11.2).
Pour les objets, c'est la référence à l'objet qui est passé par valeur, donc dupliqué et pas l'objet lui même, d'ailleurs si tu ajoutes/supprimes des lignes d'une datastore passée en argument par valeur, l'appelant voit les modifications effectuées par l'appelé.
Hors ligne
Bonjour,
Oui, j'ai été un peu approximatif. En fait, pour les objets, il devrait toujours être passé par référence même si l'argument de passage est de type value (Il devrait s'agir d'un pointeur sur 32 bits je suppose).
J'ai constaté un large changement de comportement selon que le passage est de type value ou reference. Par reference, on constate aucun changement de l'occupation mémoire tandis que par value on a l'impression que l'occupation mémoire s'accroit selon la quantité de données "on a l'impression qu'il y a une duplication des données". J'admet que pour un objet, on devrait s'attendre à un comportement strictement identique dans les 2 cas, mais ce n'est pas le cas dans la réalité.
Nous avons réglé simplement des gros problèmes d'occupation excessive de la mémoire en modifiant simplement le type de passage d'arguments de "value" à "reference". Ceci est effectivement à prendre au conditionnel, ce problème était peut être spécifique à la version de Powerbuilder que nous utilisions à l'époque à vérifier sur d'autres versions, certaines versions de Powerbuilder sont connues pour leur "memory leak".
Hors ligne
Garth a écrit:
...C'est dommage que rien n'existe dans PB pour savoir ce que consomme chaque objet de l'appli en mémoire
Hors ligne
Je reviens sur le post pour dire qu'on a finit par trouver l'origine de notre problème...
notre appli est affichée sur chaque poste sur 2 écrans.
dans l'appli, on gérait une variable de type array dans laquelle on stockait une ino spécifiant si la fenêtre était ouverte sur l'écran de gauche ou sur l'écran de droite du type gs_fenetre_ecran[x] = 'D' ou 'G'. Or, on utilisait comme index du tableau le handle de la fenêtre que nous renvoyait windows pensant que PB créait uniquement en mémoire la référence à l'index spécifiée....
L'erreur dans notre raisonnement c'est que si on créé un tableau avec un index x, PB lui créé pas un tableau de 1 élément mais un tableau de x élément, même si les élément de 1 à x-1 ne sont pas renseigné. et comme Windows renvoie des handles immenses du 15984420 on se retrouvaient avec des tableaux énormes qui explosaient la mémoire.
Voilà pour la petite histoire... Ca peut servir ;-).
Hors ligne
L'erreur dans notre raisonnement c'est que si on créé un tableau avec un index x, PB lui créé pas un tableau de 1 élément mais un tableau de x élément, même si les élément de 1 à x-1 ne sont pas renseigné. et comme Windows renvoie des handles immenses du 15984420 on se retrouvaient avec des tableaux énormes qui explosaient la mémoire.
Ah ben voui...
On dirait que cette façon d'utiliser le tableau s'apparente plus à une table de hachage (dictionnaire) plutôt qu'à un tableau.
Okazou, il existe une possibilité d'utiliser des hashtables en pb, en passant par une extension PBNI : PbniHash
Hors ligne