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

Java Discussion :

Lancement Processus: plus lents depuis java / terminal


Sujet :

Java

  1. #1
    Nouveau membre du Club
    Inscrit en
    Mai 2004
    Messages
    65
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 65
    Points : 33
    Points
    33
    Par défaut Lancement Processus: plus lents depuis java / terminal
    Bonjour,

    Je travaille sur une programme qui lance plusieurs processus :


    Ceci lance des exécutables (écrit en c) qui réalisent des caluls très compliqués : plusieurs heure sd'éxécution, et qui affichent les résultats sans cesse dans la console.

    Le temps d'exécution est donc primordiale, et l'éxécution est plus longue quand je lance ce programme depuis java que depuis le terminal.

    Il y a t'il une raison à cela ?

    Merci d'avance pour votre aide.

  2. #2
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 413
    Points : 1 993
    Points
    1 993
    Par défaut
    Le volume de données de la sortie standard est-il important?

    Il se peut que la sortie des données ralentit ton programme C. En effet, la sortie est bloquante.

    Commentaire:
    Avec ton code, il ya une possibilité (peu probable) de blocage du programme C.
    Imaginons le scénatio suivant, ton progamme génère un volume important sur le sortie d'erreur et la sortie standard. Le tampon de la sortie d'erreur se remplit car il n'est jamais lu. Et quand il sera plein, ton programme C se bloquera
    Bien le bonjour chez vous
    Jowo

  3. #3
    Membre émérite
    Avatar de xavlours
    Inscrit en
    Février 2004
    Messages
    1 832
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 1 832
    Points : 2 410
    Points
    2 410
    Par défaut
    Le ralentissement n'est il pas simplement du au fait qu'un programme java tourne en meme temps ?
    "Le bon ni le mauvais ne me feraient de peine si si si je savais que j'en aurais l'étrenne." B.V.
    Non au langage SMS ! Je ne répondrai pas aux questions techniques par MP.
    Eclipse : News, FAQ, Cours, Livres, Blogs.Et moi.

  4. #4
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 413
    Points : 1 993
    Points
    1 993
    Par défaut
    Citation Envoyé par xavlours
    Le ralentissement n'est il pas simplement du au fait qu'un programme java tourne en meme temps ?
    Normalement, le programme Java est bloqué sur la sortie standard. Quand une "chaîne de caractère" est disponible, il la lit et il l'affiche.

    Remarque:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    resultat = new String(bufferedReaderInputStream.readLine());
    Il n'est pas nécessaire d'instancier une nouveau String.

    En plus, il se peut qu'à la première lecture, la méthode readLine() returne un null.

    Correction:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    while ((resultat = new String(bufferedReaderInputStream.readLine()) != null) {
       System.out.println(resultat);
    }
    Bien le bonjour chez vous
    Jowo

  5. #5
    Nouveau membre du Club
    Inscrit en
    Mai 2004
    Messages
    65
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 65
    Points : 33
    Points
    33
    Par défaut
    Le volume de données de la sortie standard est-il important?
    Oui, il est très important le programme affiche tous ses calculs, il affiche tellement que ca défile très vite dans la console.

    Le tampon de la sortie d'erreur se remplit car il n'est jamais lu. Et quand il sera plein, ton programme C se bloquera
    Mais je le lis tout le temps donc je ne pense pas que ca soit ca. De plus j'ai un ralentissement, pas un blocage.

    Le ralentissement n'est il pas simplement du au fait qu'un programme java tourne en meme temps ?
    J'ai lancé dans la console avec le programme java qui tourne a coté et eclipse : plein d'application bien lourde. Résultat, en ligne de commande c'est toujours plus rapide.

    Il n'est pas nécessaire d'instancier une nouveau String.

    En plus, il se peut qu'à la première lecture, la méthode readLine() returne un null.
    Merci, j'ai corrigé.

    Ce ne serais pas possible que ca soit du au flux important de donnée généré que j'affiche avec des println dans la console ?

  6. #6
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 413
    Points : 1 993
    Points
    1 993
    Par défaut
    Citation Envoyé par Zapan
    Le volume de données de la sortie standard est-il important?
    Oui, il est très important le programme affiche tous ses calculs, il affiche tellement que ca défile très vite dans la console.

    Le tampon de la sortie d'erreur se remplit car il n'est jamais lu. Et quand il sera plein, ton programme C se bloquera
    Mais je le lis tout le temps donc je ne pense pas que ca soit ca. De plus j'ai un ralentissement, pas un blocage.
    Je parle d'une erreur possible. En effet, tu lis d'abord la sortie standard puis la sortie d'erreur. Le problème surviendrai si ton processus C écrit dans sa sortie d'erreur tandis que Java attend sagement des données sur la sortie standard.

    Citation Envoyé par Zapan
    Le ralentissement n'est il pas simplement du au fait qu'un programme java tourne en meme temps ?
    J'ai lancé dans la console avec le programme java qui tourne a coté et eclipse : plein d'application bien lourde. Résultat, en ligne de commande c'est toujours plus rapide.
    Beaucoup plus rapide?

    Citation Envoyé par Zapan
    Il n'est pas nécessaire d'instancier une nouveau String.

    En plus, il se peut qu'à la première lecture, la méthode readLine() returne un null.
    Merci, j'ai corrigé.

    Ce ne serais pas possible que ca soit du au flux important de donnée généré que j'affiche avec des println dans la console ?
    Ne serai-t-il pas envisageable d'écrire les données dans un fichier?
    Bien le bonjour chez vous
    Jowo

  7. #7
    Nouveau membre du Club
    Inscrit en
    Mai 2004
    Messages
    65
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 65
    Points : 33
    Points
    33
    Par défaut
    Citation Envoyé par jowo
    Je parle d'une erreur possible. En effet, tu lis d'abord la sortie standard puis la sortie d'erreur. Le problème surviendrai si ton processus C écrit dans sa sortie d'erreur tandis que Java attend sagement des données sur la sortie standard.
    Je ne peux pas lire dans les deux buffers à la fois. Mais j'ai utilisé des try ... catch pour ce cas là. Ce n'est pas suffisant ?


    Citation Envoyé par jowo
    Beaucoup plus rapide?
    Je ne sais pas avec précision, je vais mesurer.
    Pour décrire lecomportement, le programme semble aller à une vitesse normal et au bout de quelques secondes s'arrête, et repart... ainsi de suite.

    Citation Envoyé par jowo
    Ne serai-t-il pas envisageable d'écrire les données dans un fichier?
    Ce serais possible je pense, et j'afficherais juste si il y a une erreur.

  8. #8
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par Zapan
    Je ne peux pas lire dans les deux buffers à la fois. Mais j'ai utilisé des try ... catch pour ce cas là. Ce n'est pas suffisant ?
    Non ce n'est pas suffissant et cela peut te poser des problèmes comme cela a été dit...
    Les flux sortant des applications lancé par Runtime.exec() sont copier dans des buffers (pas très grand, et cela dépend de la JVM).
    Si un de ces buffers est plein, l'application sera bloqué en écriture jusqu'à ce que ce buffer soit lu.

    Donc dans ton cas si ton programme écrit trop de caractères dans le flux d'erreur, cela risque de tout bloqué :
    • Ton application en C attendra que le buffer stderr soit lu pour continuer.
    • Ton application Java attendra que ton programme C soit fini pour sortir de la boucle de lecture de stdout.

    Bref chacun de tes programmes est en attente de l'autre...

    Pour éviter cela il faut lire le flux d'erreur dans un thread séparé...

    Note : je ne pense pas que ce soit l'origine de ton problème car cela provoque un vrai blocage, mais c'est important de gérer cela car cela peut éviter de se demander pourquoi le programme bloque en cas d'erreur



    Autre remarque : tu ne fermes pas tes flux ce qui n'est pas très propre...




    Enfin ton problème vient surement du fait que tu utilises la méthode readLine() de BufferedReader. En effet pour chaque ligne que tu lit, un nouvel objet String sera crée.

    Si comme tu le dit le programme génère un grand nombre de ligne, tu te retrouve avec un grand nombre d'objet instancié, et donc une grosse consommation mémoire. Le comportement que tu décris semble correspondre à un passage forcé du Garbage Collector car il n'y a plus de mémoire disponible (il libère toutes les instances de String que tu as crée, d'où une perte de temps assez conséquente).


    Pour remédier à cela il faudrait que tu utilises le même objet en mémoire pour lire les données... surtout que tu te contentes de renvoyer les données dans le flux de sortie de ton application...


    Ce qui pourrait donner :
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    	protected void dumpStreamAndClose (InputStream in, OutputStream out) {
    		try {
    			byte[] buffer = new byte[1024];
    			int read;
     
     
    			while ( (read = in.read(buffer) )>=0) {
    				out.write(buffer, 0, read);
    			}
     
    		} catch (IOException lException) {
    			// TODO Auto-generated catch block
    			lException.printStackTrace();
    		} finally {
    			try {
    				in.close();
    			} catch (IOException lException) {
    				lException.printStackTrace();
    			}
    		}
     
    	}
     
     
    	private int executeCommande (String[] commande) {
     
     
    		File repertoireTravail = new File(cheminAppli);   
    		final Process process1;
    		try {
    			process1 = Runtime.getRuntime().exec(commande, null, repertoireTravail);
    		} catch (IOException lException1) {
    			// TODO Auto-generated catch block
    			lException1.printStackTrace();
    			return -1;
    		}
     
    		new Thread() {
    			public void run() {
    				dumpStreamAndClose(process1.getErrorStream(), System.err);
    			}
    		}.start();
     
    		dumpStreamAndClose(process1.getInputStream(), System.out);
     
    		boolean ended = false;
    		while (!ended) {
    			try {
    				process1.waitFor();
    				ended = true;
    			} catch (InterruptedException lException) {
    				// on gère le cas ou l'attente est interrompue...
    			}
    		}
     
    		int error = process1.exitValue();
    		if (error != 0){	
    			System.out.println(" $   Erreur numero : " + error + "\n $   Fin de la simulation.\n");
    		}
    		return error;
     
    	}

    La méthode dumpStreamAndClose() copie un flux dans un autre en utilsiant directement un buffer de byte, afin d'éviter d'allouer de la mémoire à chaque lecture. Le Thread permet de lire le flux stderr en parallele...

    Enfin il est preferable d'entourer le waitFor() par une boucle afin d'être sûr que le process est bien terminé (la méthode peut être intérrompue alors que le programme n'est pas forcément terminé).

    Sur une commande qui dure 3 secondes avec ta méthode, je gagne environ une seconde comme cela...

    a++

    [edit] je viens de m'apercevoir d'un petit oubli... Il faudrait fermet le flux stdin si on ne l'utilise pas. Un simple process.getOutputStream().close() devrait faire l'affaire...

Discussions similaires

  1. Lancement de procédure Iserie depuis Java sous windows
    Par phenix76 dans le forum Général Java
    Réponses: 0
    Dernier message: 08/10/2009, 18h50
  2. Réponses: 2
    Dernier message: 25/09/2009, 10h44
  3. Plantage si lancement depuis un terminal
    Par Ulath0 dans le forum Débuter
    Réponses: 11
    Dernier message: 23/01/2009, 10h23
  4. Lancement Xterm depuis Java / Linux
    Par reggs35 dans le forum Langage
    Réponses: 3
    Dernier message: 19/12/2008, 09h06
  5. [débutant]lancement d'une commande Unix ou LInux depuis Java
    Par msiramy dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 30/09/2005, 18h10

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