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

EDT/SwingWorker Java Discussion :

[Swing et multi Thread] Ralentissements étranges


Sujet :

EDT/SwingWorker Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 7
    Par défaut [Swing et multi Thread] Ralentissements étranges
    Bonjour à tous.

    Je rencontre un problème dont je ne parviens à trouver la solution :

    Je travaille sur un programme qui réalise un long traitement itératif sur une structure de données relativement volumineuse.
    Le traitement dure un peu plus d'1 heure et consiste en environ 1000 itérations qui durent environ 4 sec chacune.

    Je souhaite afficher des résultats intermédiaires toutes les 10 itérations.
    L'affichage doit accéder à l'ensemble des données pour les afficher.

    J'ai procédé ainsi :
    • Un thread de calcul séparé boucle sur les 1000 itérations (cela permet à l'utilisateur de stopper le traitement quand il le souhaite)

    • Toutes les 10 itérations, ce thread appelle mainPanel.repaint(); Cela demande au thread de swing de réafficher le panel principal, le thread de swing va donc, de façon concurente, vouloir accéder aux données. Pour éviter tout problème, le thread de calcul fait un sleep(1000); juste après l'appel à repaint() ce qui est largement suffisant pour réaliser l'affichage. Puis le calcul reprend et ainsi de suite.


    Voici donc mon problème :
    Les 10 premières itérations durent 4 secondes chacune, comme prévu.
    Puis, dès qu'un premier affichage a été réalisé, toutes les itérations sont 2 fois plus lentes (8 sec.) et ce jusqu'à la fin du programme !!
    Cependant, tout est exactement comme durant les 10 premières itérations : le thread de calcul est seul à travailler, sur les mêmes données.
    Je n'y comprend rien.
    Si je ne fais aucun affichage, les 1000 itérations ont la durée normale de 4 sec.

    Ainsi dès qu'un autre thread (swing) veut accéder aux mêmes données, quand bien même ce n'est pas de façon concurrente, car j'ai fait en sorte que le thread principal soit stoppé pendant ce temps, alors tout est ralenti ...

    J'ai une petite idée, mais ça me parait invraisemblable et je ne connait pas assez bien le fonctionnement interne de JAVA :
    • Ma structure de données contient plein de Vector et autres données thread safe.

    • Si Java voit qu'un seul thread accède à ces données, il n'active pas le "thread safe".

    • Dès que Java voit qu'un 2ème thread accède aux données, même de façon non concurrente, il active le "thread safe", ce qui ralentit tout, et cette activation perdure tout le reste du programme.

    Cela est-il possible ?
    comment peut-on corriger ce comportement étrange.

    Auriez-vous des idées pour m'aider ?

    Merci d'avance.

    (j'utilise NetBeans 6.8 et JRE 1.6.0_04)

  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
    Il nous faut du code pour analyser le problème.
    Le Thread-safe n'est pas "débrayable" par la JVM.
    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 émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    Bonjour.

    Citation Envoyé par lemmingou2010 Voir le message
    Le traitement dure un peu plus d'1 heure et consiste en environ 1000 itérations qui durent environ 4 sec chacune.
    Je souhaite afficher des résultats intermédiaires toutes les 10 itérations.
    Dès qu'il s'agit de traiter des résultats intermédiaire dans le cadre d'une IHM Swing, j'ai un réflexe : SwingWorker.

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 7
    Par défaut
    Citation Envoyé par Deaf Voir le message
    Bonjour.
    Dès qu'il s'agit de traiter des résultats intermédiaire dans le cadre d'une IHM Swing, j'ai un réflexe : SwingWorker.
    J'ai essayé d'utiliser un SwingWorker.
    Le résultat est le même.
    en effet, SwingWorker fait à peu près ce que je faisais avant (à savoir envoyer dans l'EDT les refresh de ProgressBar et d'affichage).

    Le problème semble plus subtile : il y a vraiment un ralentissement qui semble s'opérer dès qu'un autre thread tente d'accéder aux données, même si ce n'est pas en même temps.

  5. #5
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par lemmingou2010 Voir le message
    J'ai essayé d'utiliser un SwingWorker.
    Le résultat est le même.
    On pourrait voir le code ?

    a++

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 7
    Par défaut
    Désolé, c'est un peu compliqué de mettre du code qui soit comprehensible, il est un peu dense.

    En revanche, j'ai résolu mon problème ainsi :
    j'ai transformé tous mes Vector en ArrayList, et il n'y a plus de problème.

    Ceci confirme que
    • Java (au moins depuis la 1.6) sait optimiser les Vector, pour obtenir les mêmes perf que ArrayList, mais uniquement si un unique Thread tente d'accéder au Vector durant toute la durée du programme = la fameuse optimisation "Biased Locking"
    • Les perf dégringolent dès que Java voit que plusieurs Thread différents ont tenté d'accéder à un Vector (même si pas en même temps) : il "réactive la synchronisation" pour toutes les méthodes synchronized


    On ne peut mesurer cette baisse de perf que dans mon cas de figure, c'est à dire :
    • dans le cas de code qui fait du calcul intensif sur des vecteurs (ou autres classes thread safe)
    • qui commence avec un seul thread, puis, qui fait intervenir de nouveau thread par la suite (EDT, par ex.)


    Ce résultat est intéressant, et peut expliquer pourquoi paralléliser un calcul sur 2 CPU peut, dans certains cas, ne rien faire gagner en perf si on utilise beaucoup de classe thread safe ! (ca m'est déjà arrivé) :
    • le fait de mettre 2 CPU va en théorie 2 fois plus vite
    • mais Java réactive la synchronisation, ce qui peut faire perdre un facteur 2 en perf.

    Et je ne parle pas des temps d'attente perdus par les thread lors des synchronisation, si le programme est mal codé

    Bigre c'est compliqué d'optimiser du Java quand même.

  7. #7
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par lemmingou2010 Voir le message
    Bigre c'est compliqué d'optimiser du Java quand même.
    Avec SwingWorker tout ceci est géré pour toi... donc il ne devrait pas y avoir de problème.

    a++

  8. #8
    Membre confirmé
    Profil pro
    Développeur Java
    Inscrit en
    Août 2008
    Messages
    176
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Août 2008
    Messages : 176
    Par défaut
    Citation Envoyé par lemmingou2010 Voir le message
    Bonjour à tous.

    J'ai une petite idée, mais ça me parait invraisemblable et je ne connait pas assez bien le fonctionnement interne de JAVA :
    • Ma structure de données contient plein de Vector et autres données thread safe.

    • Si Java voit qu'un seul thread accède à ces données, il n'active pas le "thread safe".

    • Dès que Java voit qu'un 2ème thread accède aux données, même de façon non concurrente, il active le "thread safe", ce qui ralentit tout, et cette activation perdure tout le reste du programme.

    Cela est-il possible ?
    comment peut-on corriger ce comportement étrange.

    Auriez-vous des idées pour m'aider ?

    Merci d'avance.

    (j'utilise NetBeans 6.8 et JRE 1.6.0_04)
    dans la version 6 il ya une amélioration de ce type " Biased Locking" qui fonctionne comme tu la mentionner, pour vérifier cela essai de désactivé cette option : -XX :-UseBiasedLocking dans les paramètre de la JVM

    dans la version 1.6 update 18 il y a plusieurs amélioration concernant le multithreading essai d'utilisé cette version et voir la différence.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 7
    Par défaut
    Citation Envoyé par Sfaxiano Voir le message
    dans la version 6 il ya une amélioration de ce type " Biased Locking" qui fonctionne comme tu la mentionner, pour vérifier cela essai de désactivé cette option : -XX :-UseBiasedLocking dans les paramètre de la JVM

    dans la version 1.6 update 18 il y a plusieurs amélioration concernant le multithreading essai d'utilisé cette version et voir la différence.
    En effet !
    En lisant la doc du "Biased Locking", je comprend qu'il y a en effet une optimisation qui ne fonctionne que si 1 seul thread essaie d'accéder à des objets thread safe : la JVM "désactive les synchronisation".

    En effet, en désactivant cette option (-XX :-UseBiasedLocking) je constate désormais que toutes les itérations durent longtemps (8 sec.)
    Ainsi, désactiver l'option m'a permis de comprendre que c'est cette optimisation qui permettait d'aller 2 fois plus vite au début du traitement.
    Mais cela ne m'aide pas à résoudre mon problème :
    • avec l'optimisation "Biased Locking", la JVM est plus rapide jusqu'au 1er affichage, puis tout le reste du traitement est lent (puisque l'affichage utilise un autre thread que celui du calcul (EDT)
    • sans l'optimisation, la JVM "active la synchronisation" dès le début du traitement et le traitement est lent tout le temps


    -> Je ne sais donc toujours pas comment obtenir les bonnes performances (4 sec par itération) durant tout le traitement, en permettant un affichage de temps en temps, sans que la JVM ne "réactive la synchronisation"

    Je sais que mon problème est très particulier, et que peu d'entre vous ont dû le constater, mais si un expert en la matière pouvait m'aider ...

  10. #10
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    Citation Envoyé par lemmingou2010 Voir le message
    Les 10 premières itérations durent 4 secondes chacune, comme prévu.
    Puis, dès qu'un premier affichage a été réalisé, toutes les itérations sont 2 fois plus lentes (8 sec.) et ce jusqu'à la fin du programme !!

    ...

    Ainsi dès qu'un autre thread (swing) veut accéder aux mêmes données, quand bien même ce n'est pas de façon concurrente, car j'ai fait en sorte que le thread principal soit stoppé pendant ce temps, alors tout est ralenti ...
    Je ne suis pas sûr d'avoir bien saisi, mais d'un côté tu déplore que le traitement soit plus long, mais de l'autre tu le stoppes pendant l'affichage?

    Le plus simple serait d'extraire le squelette de ton appli pour que l'on puisse l'examiner.
    Tu peux remplacer ton traitement par un sleep(4000) pour simuler le traitement par exemple.

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

Discussions similaires

  1. [Swing & Threads] Ralentissements
    Par HunTR dans le forum EDT/SwingWorker
    Réponses: 9
    Dernier message: 02/04/2010, 11h01
  2. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 10h00
  3. [SWING] JPanel multi-threading
    Par raj dans le forum AWT/Swing
    Réponses: 3
    Dernier message: 12/02/2007, 08h52
  4. [swing] P4 et multi-threading
    Par xxaragornxx dans le forum EDT/SwingWorker
    Réponses: 2
    Dernier message: 16/11/2005, 19h55
  5. [Kylix] exception qtinft.dll et multi-threading
    Par leclaudio25 dans le forum EDI
    Réponses: 3
    Dernier message: 27/03/2003, 19h09

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