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

2D Java Discussion :

Consomation memoire excessive programe java (BufferedImage)


Sujet :

2D Java

  1. #1
    Membre averti
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Octobre 2011
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Octobre 2011
    Messages : 50
    Par défaut Consomation memoire excessive programe java (BufferedImage)
    Bonjour,
    Je suis en train de finir une application qui me permet de numériser des documents pour les mettre en bdd.
    Pour faire simple l'utilisateur peut créer un lot de documents a numériser.
    On sélectionne ce lot dans la fenêtre principale qui l'affiche dans une nouvelle jframe.
    Dans cette jframe, les documents numérisés s'affichent dans une jtable et la sélection d'une page l'affiche dans un jpanel(avec pdfRenderer).
    pour optimiser la navigation et éviter la latence crée par la création de l'image a partir du pdf chaque objet document contient une bufferedImage avec la première page du document a afficher.
    le problème est que cela consomme énormément de mémoire.
    De plus je pense avoir des fuites de mémoire car lorsque je ferme la jframe avec un dispose la consommation mémoire ne diminue que peu.
    existe t-il un moyen de voir combien de mes objets sont chargés en mémoire et leur taille?
    si quelqu'un a une idée pour optimiser tout ça je prends.

    Merci beaucoup.

  2. #2
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Pour réduire la consommation mémoire, rien de magique :
    1. soit tu augmentes l'usage CPU en calculant en fonction du besoin,
    2. soit tu augmentes l'usage disque en stockant sur disque les images et en lisant à la demande.

    Si la RAM diminue peu (vu par l'OS), ce n'est pas forcément une fuite mémoire : la JVM conserve la zone mémoire libérée et ne la redonne pas immédiatement à la machine.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  3. #3
    Membre averti
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Octobre 2011
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Octobre 2011
    Messages : 50
    Par défaut
    Merci.
    Le fichier pdf est déjà sur le disque et le calcul du rendu par PdfRenderer est très lent (environ 250ms)

    Lors de la navigation entre les différents pdfs cette latence de 250ms est pénible (j'ai testé plusieurs librairie de rendu gratuite : pdfbox, icepdf, jpedal le temps de rendu est équivalent ou pire pour icepdf), c'est pour cette raison que j'ai décidé de stocker dans mon objet document un attribut Image avec le rendu de la premiere page du pdf créé a l'ouverture de la jframe. .

    Du coup la bufferedImage n'est peut être pas adapté pour mon utilisation. existe t-il un moyen de la compresser pour la stocker?
    Ou peut être un autre type plus adapté qui occuperait moins de place en ram.

    Merci encore.

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    bah, tu peux stocker les images en png et le lire à la volée, mais tu va tourner en boucle. Lire le png prend aussi du temps, peut être même plus que du rendu pdf. 250ms, c'est peu selon moi. Dans quel cas d'utilisation c'est gênant?

  5. #5
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Ah.... 250ms c'est très court. Comme dit Tchize, même une lecture d'une image avec affichage sera dans cet ordre de grandeur.
    Je pensais que c'était après le clic sur une ligne de la JTable que le rendu était lent. En relisant ton premier post, j'imagine que la lenteur se situe sur l'affichage de la JTable ?
    Pour afficher la JTable, tu calcules le rendu PDF de chaque PDF pour en afficher une miniature par ligne. C'est ce traitement qui est lent ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  6. #6
    Membre averti
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Octobre 2011
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Octobre 2011
    Messages : 50
    Par défaut
    Ce traitement au chargement est lent, mais cela n'est pas trop gênant.

    C'est en effet au clic sur la jtable quand on sélectionnait le document, que l'affichage du pdf était lent. Du coup lorsque l'on navigue dans la jtable avec les flèches du clavier par exemple cette petite latence bloque le programme tant que le pdf n'est pas affiché et la c'est long (250 ms etant une moyenne parfois cela peut être 800). J'avais testé avec des threads pour lancer le rendu (la latence a la navigation disparait), mais comme je ne suis pas très doué il y avais également des problèmes de fuites, des instances ne ce fermaient pas bien et cela finissait par consommer beaucoup de mémoire également.

    C'est pour cette raison que lors du chargement initial je conserve la bufferdImage dans une liste c'est rapide mais gourmand. Si seulement il était possible de compresser une BufferedImage...

    Je vais continuer mes tests, du coup je vais peut être remettre le rendu du pdf dans un swingworker et tenter le gérer tout ça proprement.

    Si une idée vous viens je prends

    Merci beaucoup.

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par mrboliboli Voir le message
    C'est pour cette raison que lors du chargement initial je conserve la bufferdImage dans une liste c'est rapide mais gourmand. Si seulement il était possible de compresser une BufferedImage...
    C'est certainement le cas. Pour commencer il serait sûrement moins long de charger une image JPEG que de générer l'image d'un PDF. Donc il suffit d'enregistrer les images générées, en JPEG, dans un cache sur le disque dur. C'est une pratique courante.

    Ensuite, tu pourrais simplement générer des images plus petites et qui donc prennent moins de place. Au pire en les affichant plus grandes que leur taille réelle en pixel. Ce sera moins beau mais ça prendra moins de mémoire. (D'ailleurs je me demande un peu si c'est bien toi qui choisit la taille des images et pas plutôt le renderer PDF. Si c'est le cas bien sûr qu'il faut commencer par redimensionner l'image.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par thelvin Voir le message
    C'est certainement le cas. Pour commencer il serait sûrement moins long de charger une image JPEG que de générer l'image d'un PDF.
    Là je ne suis pas convaincu: entre les algorithmes de compression du JPEG faisant intervenir foison de transformations de fourrier, et une première page d'un PDF qui ne contiendrait que 2 lignes de texte parce que c'est le titre.... Bref, tout dépend du PDF.


    Pour le problème de navigation, selon moi c'est facile:

    un Timer swing, réglé sur 100ms, chargé d'afficher la page à la fin du timer
    Quand tu navigue, tu réinitialise le timer => on n'affiche pas tant qu'on n'est pas resté au moins 100ms sur la ligne.
    Pour ne pas bloquer l'affichage, un swingworker: le timer lance le swingworker, celui-ci fait le rendu PDF.

    Après, rien ne t'empêche de garder un cache de ce que tu as déjà rendu, avec un stratégie type LRU ou autre.

    Maintenant, le cache PDF ou PNG n'est pas nécessairement non plus une mauvasie idée. Ce qui serait, selon moi, une mauvaise idée, ce serait de convertir d'office tous les PDF au démarrage, il faudrait plutot le faire à la demande. Si j'ai un dossier avec 5000 PDFs, j'ai peut être pas envie d'attendre 2 minutes avant de me rendre compte que j'ai ouvert le mauvais dossier

  9. #9
    Membre averti
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Octobre 2011
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Octobre 2011
    Messages : 50
    Par défaut
    Merci a tous.

    Après beaucoup de tests, j'ai réussi à réduire considérablement l'occupation mémoire. Le coupable était PdfRenderer.

    J'ai pris un PDF que j'ai converti en png, je me suis amusé à mesurer le temps de calcul de rendu du pdf (PdfRenderer), puis celui du png.
    pour ce document environ 700 ms pour le rendu du pdf pour environ 250ms pour le rendu du png.

    Puis je me suis rendu compte que chaque PDF occupait un espace mémoire important même sans bufferedImage conservée. Dans JvisualVm je me suis rendu compte qu'il y avais des Bytes[] qui occupait beaucoup de mémoire. cette mémoire n’était jamais libérée même a la fermeture de la fenêtre. Comme je n'utilise pas de tableau de byte, j'ai commencé à suspecter PdfRenderer lui même.

    Dans mon petit projet de test j'ai implémenté Jpedal lgpl à la place de PdfRenderer et miracle, une occupation mémoire raisonnable, puis infime après passage du gc.

    J'ai donc mis Jpedal dans mon projet, je suis passé de 1,7go de ram occupé pour 30 docs a 20/30 mo pour 120 documents (après passage du gc sans jamais dépasser 150mo pendant la génération des images). j'ai également réduit la taille et la qualité des images nécessaire pour les miniatures pour arriver a ce résultat.

    La méthode du swingTimer me plait bien j'ai donc viré les bufferedImage et je suis en train d'ajouter le swingTimer (que je n'ai jamais utilisé).

    Pour info en terme de rapidité de rendu le premier document généré par jPedal est long, les suivants sont beaucoup plus rapide (en moyenne: 1er doc environ 1s de rendu, entre 100 et 200ms pour les suivants.

    Merci encore.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. program java pour la composition des service web
    Par bleu angle dans le forum Services Web
    Réponses: 0
    Dernier message: 04/04/2009, 12h33
  2. [tomcat][memoire] java.net.URL et fuite mémoire
    Par Seiya dans le forum Tomcat et TomEE
    Réponses: 6
    Dernier message: 09/03/2009, 10h41
  3. Lanceur de programe Java
    Par Piolet dans le forum Applications et environnements graphiques
    Réponses: 0
    Dernier message: 05/03/2008, 12h54
  4. Récuperer des données par program Java
    Par irouni dans le forum Langage
    Réponses: 1
    Dernier message: 08/02/2008, 11h02
  5. Probleme Programation JAVA débutant
    Par tomtom62136 dans le forum Langage
    Réponses: 1
    Dernier message: 03/03/2006, 12h07

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