LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

garbage collection sous labwindows

Bonjour,

Nous avons un problème d'erreur "-12" (Out of memory) d'une fonction "NewBitmap" sur une image de 1200pointsx18432points (22 Mo).

En fait cette erreur survient lorsque l'on vient de libérer un grand nombre (42000 !) de petites allocations de 18ko, et que l'on essaye de

faire cette grande allocation.

La question est donc : existe-t-il un procédé de "garbage collection" dans l'environnement LabWindows ?

Dans notre cas le système ne peut plus, même après 15 minutes, réallouer l'espace nécessaire à cette fonction.

Pour lever les doutes éventuels, nous utilisons la fonction "CVIDynamicMemoryInfo" afin de tracer la mémoire utilisée dans notre application,

et il est clair que les allocations dynamiques de mémoire (par des malloc ou des NewBitmap) sont toutes correctement lbérées.

Nous souhaitons pouvoir nettoyer l'espace mémoire fraîchement libéré pour pouvoir à nouveau allouer soit un gros bloc, soit beaucoup de petits.

Sincères salutations,

Franck Dubreuil

 

0 Kudos
Message 1 of 10
(5,433 Views)

il n'existe aucun procédé de garbage collection sous CVI, puisque le langage utilisé est le C standard qui ne definit pas de garbage collection et que le runtime CVI utilise les functions d'allocations mémoire du système d'exploitation (c'est a dire, Windows) qui n'ont pas non plus de garbage collection. de plus, l'utilisation de la memoire virtuelle sous windows rend les pénuries de memoire tres fortement improbables: le systeme d'exploitation va "swapper" et placer la memoire inutilisée sur le disque dur pour liberer la RAM.

 

par contre, la fonction NewBitmap() possède surement une limitation (tres certainement liée a une limitation du système d'exploitation, cf. cet article ou cet article). j'ai en effet reussi a reproduire votre probleme (sans faire aucune petite allocation au prealable): chez moi, la taille maximum de la bitmap est de 16588 octets (0x40CC).  cette limitation n'est pas documentée, donc le probleme ne se situe peut etre pas la.

 

d'un autre coté, je ne suis pas certain que l'utilisation de NewBitmap() soit une très bonne idée avec une image de cette taille. que cherchez vous a faire exactement ? (pour l'affichage a l'ecran il y a des solutions bien plus efficaces que d'allouer une bitmap de cette taille, qui ne peut de toute facon pas etre vue dans son ensemble a moins d'avoir un mur d'ecran...)

0 Kudos
Message 2 of 10
(5,415 Views)

Merci de votre réponse concernant la fonction de garbage collection.

Pour donner plus de détail sur le symptôme, nous utilisons windows server 2003 Standard Edition avec 4Go de RAM, et nous manipulons une image de 32000 lignes par 18432 points de large, soit 600Mo.

Nous créons une bitmap de 18432 points de large (plaine largeur) avec la fonction NewBitmap, mais seulement sur 1200 lignes de haut.

Cette bitmap est affichée partiellement avec la fonction "CanvasDrawBitmap" dans un Canvas de 600(haut)X1024(large), le positionnement horizontal se faisant à l'aide d'un Slide numérique qui gère le pointage dans la bitmap, comme le ferait un ascenseur.

Pour le déplacement vertical dans l'image, nous utilisons la fonction "SetBitmapData" afin de déplacer la bitmap dans le gros buffer de l'image globale, là aussi avec un Slide numérique en ascenseur, afin de ne pas créer une bitmap sur la totalité de l'image.

La première manipulation (malloc(), NewBitmap(), puis libération par free() et DiscardBitmap() ) se passe très bien.

La deuxième manipulation se passe mal après exécution d'une autre fonction qui alloue dynamiquement (malloc, puis free ()) une grande quantité de petit buffer de 16384 octets (40 000) soit 650Mo.

L'alternance de ces deux fonctions nous pose un gros problème car elle met en évidence les phénomènes de non libération de la table des allocations pourtant libérées.

Nous souhaitons aussi préciser, afin de ne pas mélanger le problème avec les limites de la fonction "NewBitmap", que nous avons reproduit le même phénomène dans un petit logiciel séparé, où nous ne faisons que des "malloc()" et des "free()" d'une taille de 650Mo, en alternance : une fois en un grand "malloc()" de 650 Mo suivi d'un "free()", et la suivante en 40 000 "malloc()" de 16384 octets, suivi aussi d'un "free()".

En résumé, lorsque les tailles gérées par ces deux méthodes peuvent être cumulées dans la mémoire gérée par l'application LabWindows/CVI, tout va très bien et la mémoire libérée et réallouée plus tard probablement "au même endroit", mais lorsque les tailles gérées ne peuvent plus être cumulées, le problème survient car le grand buffer de 650Mo ne peut pas être alloué une seconde fois.

Un vrai bon problème de garbage collection.

Des solutions existent pour notre application, entre manipuler notre allocation par la gestion de nos pointeurs dans le grand buffer alloué une seule fois au début, ou encore lire les morceaux utiles de l'image sur le disque dur au fur et à mesure du besoin, ... mais cela impose une réécriture déplaisante de cette gestion mémoire, et malgré une allocation globale au départ, nous devons encore valider que les allocations dynamiques (listes chaînées, ...) qui restent seront correctement gérées.

Faute de meilleures nouvelles, nous allons essayer de faire le choix le plus efficace pour l'affichage, et le moins pénalisant pour le disque dur.

Si vous voyez un meilleur moyen de gérer l'image, nous sommes preneurs.

Sincères salutations,

Franck Dubreuil
0 Kudos
Message 3 of 10
(5,403 Views)

un meilleur moyen: et bien j'allais vous proposer ce que vous faites deja... je pensais que l'image faisais 1200*18432 et je vous aurais proposé d'utiliser une bitmap de 1200*1200 en specifiant lors de l'appel a NewBitmap() un pointeur vers l'une des lignes de l'image deja en memoire. mais le probleme est bien plus gros que cela.

 

je n'ai malheureusement pas pu reproduire le probleme que vous précisez avec l'utilisation de malloc() suivi de free(). je n'ai eu de probleme qu'avec la fonction NewBitmap().  le runtime CVI a peut-etre un souci dans ce cas d'allocation, mais il faut attendre l'avis d'une personne de chez NI pour s'en assurer.

 

en attendant vous pouvez essayer de tricher. n'ayant malheureusement pas pu reproduire votre probleme, les pistes que je vous donne là ne sont que des idées, qui n'auront peut etre aucun effet, ou peut etre meme un effet non désiré comme tout planter...

1. essayez l'appel suivant a la fin de la série de petite allocation/dé-allocation, juste avant de ré-allouer le grand buffer:

    HeapCompact( GetProcessHeap(), 0 );

    la fonction HeapCompact() est définie dans <windows.h>.

2. remplacez toutes les allocations memoireCVI par des allocations du systeme:

    #define cust_malloc( size ) (HeapAlloc( GetProcessHeap(), 0, size ))
    #define cust_free( block )  (HeapFree( GetProcessHeap(), 0, block ))

3. utiliser les 2 premieres methodesen meme temps.

3. utiliser l'ensemble des fonctions de gestion mémoire du système, en commencant par HeapCreate(). certaines options pourraient vous aider dans le cadre du probleme d'allocation memoire (comme creer une "low-fragmentation heap" pour la gestion memoire).

0 Kudos
Message 4 of 10
(5,397 Views)
Vous devriez faire des resampling (redimensionnement) d'image en memoire
avant de definir et remplir le bitmap.
--
Guillaume Dargaud
http://www.gdargaud.net/


0 Kudos
Message 5 of 10
(5,365 Views)

Le point sur nos améliorations :

Sur un PC windows Server 2003 R2 Standard Edition (4Go de RAM max) équipé de 4Go de RAM, le plus gros Malloc autorisé pour l'application fait 940 Mo (ça coince à 950Mo).

Nous avons donc réservé la taille mémoire nécessaire pour notre besoin dynamique (600 Mo) dès le démarrage de l'application, et nous gérons notre propre pointeur dans cette zone de mémoire,

afin d'y placer soit une grosse image de 550Mo, soit 36000 imagettes de 16384 octets (128x128), soit 589 Mo, cela sans utiliser de malloc () et de free (), mais juste en replaçant le pointeur par l'application.

Cette méthode permet de faire un seul malloc () et un seul NewBitmap () au début de l'application, et de garantir la disponibilté de la mémoire pour toute la session de fonctionnement de l'application.

Pendant l'utilisation de notre logiciel, d'autres fonctions dynamiques allouent de la mémoire (gestion de plusieurs listes chaînées comportant jusqu'à 500 000 éléments) mais il semblerait que ces listes soient mieux gérées à la libération de la mémoire, car aucun phénomène de saturation n'est apparu sur plusieurs tests cumulés.

Peut-être que Windows réalloue le même espace que celui déjà utilisé précédemment par ces listes chaînées ...

Donc tout irait bien avec cette solution si il n'y avait pas un dernier effet secondaire observé systématiquement :

Lorsque l'opérateur sort de l'application après avoir utilisé les ressources à leur maximum et à plusieurs reprises (grande image,listes chaînées de tailles maximum, ...) la relance de l'application se passe mal, c'est à dire que les ressources libérées ne sont plus réallouables pour l'application (à priori c'est la fonction NewBitmap qui ne passe pas, et sort en erreur (-12) Out of Memory).

Dans ce cas seul le redémarrage de Windows permet de décoincer la situation.

Notre client est disposé à accepter cet inconvénient puisque il n'a mormallement pas de raison de sortir de l'application lors d'une utilisation "normale".

Mais ce dernier point reste un peu génant, et la sensation qui subsiste est que le sujet n'est pas tout à fait terminé.

Si vous voyez un moyen de résoudre ce dernier phénomène, c'est à dire garantir à l'application la même taille de mémoire allouable au lancement, et même après plusieurs session de l'application sans redémarrer Windows, nous vous serions reconnaissant.

Sincères salutations,

Franck Dubreuil

 

0 Kudos
Message 6 of 10
(5,261 Views)

personellement, je souhaiterais que l'un de nos amis de NI vienne commenter ce probleme: il n'y a aucune raison pour que le malloc soit limité, et comme je l'ai déja indiqué, la seule limitation que j'ai observé se trouve dans l'appel à NewBitmap(). pourriez-vous délimiter le probleme avec un petit programme de test et le poster ici, que chacun puisse le tester avec différentes versions de CVI et de Windows ?

 

a propos du probleme au redémarrage de l'application,  tel que vous le décrivez, la limite est bien dans NewBitmap() et pas dans malloc, comme je l'ai commenté dans un message précédent. il faut absolument vérifier que vous libérez les resource en sortie du programme: free() mais aussi, et surtout, DiscardBitmap().

 
0 Kudos
Message 7 of 10
(5,256 Views)

Bonjour,

Suite à votre demande, vous trouverez ci-joint un test à exécuter sous Windows (XP, Server 2003, Vista).

Il suffit de décompresser le fichier zip joint dans un nouveau dossier.

 

La fonction permet de saisir une taille de buffer à allouer (en Mo), car la limite dépend de la machine et sa mémoire dynamique.

L'appui sur le bouton "AllocBuffer" provoque les deux actions suivantes, à la suite l'une de l'autre:

1 - Allocation d'un gros buffer de la taille saisie, et libération de ce buffer.

2 - Allocation d'autant de buffer de 16384 octets que la taille saisie le permet (pour 600 Mo, on allouera 36622 buffer), et libération de ces buffer.

Si les deux actions se sont bien passées la LED écran passe au vert, sinon au rouge.

L'intérêt du test, c'est de faire l'appui sur le bouton au moins deux fois de suite avec la même taille saisie, afin d'alterner grande allocation et nombreuses petites, puis à nouveau la grande.

 

Sur notre machine Windows Server 2003 R2 Standard Edition avec 4Go de RAM, ça coince à 950Mo.

Sur mon portable Vista SP1 avec 2Go de RAM, ça coince à 790 Mo.

Cela semble dépendre de la taille de la mémoire système, mais l'allocation qui coince est évidemment toujours la grande, une fois qu'on a fait toutes les petites.

 

Ce test très simple met bien en évidence les limites lors de l'allocation et de la réallocation des espaces de tailles différentes, et ce n'était pas si long à mettre en oeuvre ...

Sincères salutations,

Franck Dubreuil

 

0 Kudos
Message 8 of 10
(5,234 Views)

Mes excuses, le projet en question est dans ce message !!

Franck Dubreuil

 

0 Kudos
Message 9 of 10
(5,233 Views)

Bonjour,

Je me permet de vous relancer sur le phénomène décrit précedemment, et qui manque singulièrement de commentaires.

Sommes nous la seule entreprise qui utilise la mémoire de manière massive sous LabWindows ?

Franck Dubreuil

 

0 Kudos
Message 10 of 10
(5,088 Views)