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

Langage Java Discussion :

Vitesse exécution Runtime.exec()


Sujet :

Langage Java

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 20
    Par défaut Vitesse exécution Runtime.exec()
    Bonjour,

    Contexte : Application Web JAVA / Serveur Tomcat

    Je suis étonné de la lenteur d'exécution des commandes lancées par mon appli avec la méthode Runtime.exec()
    En effet, une commande lancée en shell directement me prend trois secondes au lieu de 10 lors de l'exécution du programme JAVA.

    Auriez vous une explication voire une solution pour améliorer la vitesse d'exécution de ma commande shell?

    Merci

  2. #2
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Gères tu correctement les flux standard d'entrée/sortie/erreur de ton Runtime.exec (sont ils bien consommés)?

    http://ydisanto.developpez.com/tutoriels/j2se/runtime/
    http://blog.developpez.com/adiguba/p...s-plus-simple/

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 20
    Par défaut
    Est-il nécessaire de traiter ces flux?
    Je lance simplement l'exec puis j'attends que le Process soit terminé avec waitfor() pour le moment, je ne m'occupe pas de ce qui se passe en console.

  4. #4
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 20
    Par défaut
    J'ai ajouté le traitement des flux comme indiqués dans tes liens et j'obtiens toujours le même temps. J'ai pourtant bien deux Threads séparés qui traitent le flux standard et le flux d'erreur.
    Le problème ne semble donc pas venir de là mais ca semblait etre une bonne idée, merci.

  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,


    Il faut TOUJOURS traiter les flux (ou les fermer) sous peine d'avoir un dead-lock entre les deux programmes.

    Quand à ton problème, il faudrait en savoir plus sur ta commande ? Comment tu la lances dans le shell, le code java correspondant, ce qu'elle fait, etc...


    a++

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 20
    Par défaut
    Bonjour,

    Voilà le morceau de code principal qui me sert à lancer un commande.
    J'ai donc deux threads pour gérer les flux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    final Process p;
            try {
                // Consommation de la sortie standard et de la sortie d'erreur des scripts
                p = Runtime.getRuntime().exec(command);
                new InputThread(p.getInputStream(), session).start();
                new InputThread(p.getErrorStream(), session).start();
                p.waitFor();
                exitValue = p.exitValue();
            }
            catch (IOException ex) {
                java.util.logging.Logger.getLogger(ExecScript.class.getName()).log(Level.SEVERE, null, ex);
            }
            catch (InterruptedException ex) {
                //ex.printStackTrace();
                logger.logTraceMessage(session,"<h5 class=\"error\">Unexpected error while executing" + StringEscapeUtils.escapeHtml(command.toString()) + "</h5> \n");
                exitValue = 1;
                return;
            }
    Je lance une commande shell (donc un script ".sh") via Java en utilisant le code ci-dessus qui est dans une fonction que j'appelle a chaque fois que je veux exécuter un script.
    la commande shell elle-même appelle un script en C...

    Est ce que cela vous suffit comme info? Voyez vous des pistes de réflexion sur lesquelles me pencher?

    Merci

  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 NicoTheDude Voir le message
    Je lance une commande shell (donc un script ".sh")
    Lequel ? Et que fait-il exactement ! Cela peut rentrer en compte.



    Sinon pour le code :
    • Il faut fermer les flux inutilisés (getOutputStream() dans ton cas).
    • Depuis Java 5 il faut privilégier ProcessBuilder à Runtime.exec(), en séparant bien les différents paramètres de la commande.
    • Pas besoin de créer forcément deux threads : tu peux lire un des flux dans le thread courant
    • Mieux avec ProcessBuilder tu peux cumuler les flux de sorties standard et d'erreur avec redirectErrorStream() pour n'en avoir qu'un seul à lire sans avoir besoin de créer de thread supplémentaire...


    Bref ton code pourrait ressembler à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    	final Process p = new ProcessBuilder("cmd", "/C", "dir")
    		.redirectErrorStream(true)
    		.start();
     
    	// On ferme les flux inutiles :
    	p.getOutputStream().close();
    	p.getErrorStream().close();
     
    	InputStream input = p.getInputStream();
    	try {
    		// Copie sur stdout :
    		byte[] buf = new byte[8192];
    		int len;
    		while ( (len=input.read(buf)) >= 0 )
    			System.out.write(buf, 0, len);
    	} finally {
    		input.close();
    	}
    	p.waitFor();

    a++

  8. #8
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 20
    Par défaut
    Mon script shell lance des actions de compilation sur du code C avec gcc et fait tourner une application Caml prenant en paramètre le code C par exemple.
    Je n'en sais guère plus pour le moment. Cela vous suffit il?

    Merci pour tes corrections de mon code, je vais les appliquer de ce pas, c'est sympa!

  9. #9
    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
    Il n'y a pas de raison pour que ce soit plus rapide en shell que par java, java ne fait au final qu'un appel à fork puis exec, le process créé ne dépend pas de java.

    La seul chose que je verrrais, c'est si java a une priorité moindre dans le système, tous les process qu'il pourra lancer hériteront aussi de cette priorité moindre, mais ça voudrais dire qu'on a volontairement bridé ton processus java

    Par curiosité quand tu lance dans un shell, tu lance comment, tu utilise bien la commande

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time tonApplicationShell.sh
    pour faire ta mesure? Et sur la même machine?

    Aussi quelle est la verbosité du script? Si il génére des centaines de miliers de lignes de texte et que tu stocke tout ça coté java, tu va ralentir à cause de ta consommation mémoire coté java, qui va restreindre la consommation des inputstream qui aura un effet d'engorgement sur le script. Pour faire une mesure dans l'absolu, commencer par simplement cloturer les stream (méthodes close())

  10. #10
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 20
    Par défaut
    J'utilise bien cette commande pour mesurer la vitesse d'exécution lorsque je lance en shell :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time tonApplicationShell.sh
    Les Stream ne renvoient que quelques lignes donc ce n'est pas de ce coté qu'il faut chercher... En les fermant, c'est identique.

    Oui, je compare sur la même machine bien sûr.

    "java a une priorité moindre dans le système" -> J'avais en effet pensé que ca pouvait venir du fait que mon processus lancé par java n'était pas prioritaire, comment vérifier cela?

  11. #11
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ps -eo pid,nice,user,args --sort user
    La deuxième colonne est le niveau de gentilesse, plus il est élévé, moins le processus est prioritaire.


    Regarde aussi dans les variables d'environnement, il faudrait comparer les output console des deux appels, gcc est très sensibles aux variables d'environnements pour ses opération, il suffit d'un CFLAGS=-o3 dans l'environnement par exemple pour qu'il fasse l'optimisation de code la plus poussée (et donc la compilation la plus lente)


    éventuellement rejoute ceci en tête de script

    et compare les dux sorties

  12. #12
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 20
    Par défaut
    Hmmmm... je viens de penser à quelque chose.

    J'ai créé un nouveau programme java qui ne fait que lancer le script et uniquement cela. L'exécution s'est bien passée et a été rapide.

    Cela peut peut être venir du fait que dans mon application - l'autre où c'est lent -, le lancement de ce script est fait dans un Thread particulier ?

    Je vais essayer tes commandes.

    Merci pour votre aide!

  13. #13
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 20
    Par défaut
    Bon, j'ai résolu le problème...

    Le problème est que pendant que je lance ce script, j'ai une machine virtuelle qui est en train de se lancer et qui bouffe plein de ressources.

    En effet, si j'attends la fin du lancement d ecette VM pour lancer mon script, il se termine vite.

    Désolé pour le dérangement, problème résolu.
    Merci pour votre aide.

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

Discussions similaires

  1. [RUNTIME][EXEC]
    Par adrien1977 dans le forum API standards et tierces
    Réponses: 7
    Dernier message: 30/09/2009, 16h28
  2. [Runtime][exec]Récupérer les stdout ET stderr
    Par yveslamand dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 20/05/2005, 13h37
  3. [Runtime]exec() avec une commande paramétrée
    Par nice dans le forum Général Java
    Réponses: 9
    Dernier message: 12/05/2005, 13h15
  4. [Servlet][Windows][System call]Runtime.exec
    Par lucho31 dans le forum Servlets/JSP
    Réponses: 8
    Dernier message: 18/01/2005, 11h55
  5. [Système][Runtime][Exec] Comportement étrange au lancement de BeSweet
    Par divxdede dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 06/06/2004, 09h54

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