2009-11-18 6 views
1

J'ai un réseau de threads Java (programmation basée sur le flux) communiquant via des canaux à capacité fixe - fonctionnant sous Windows XP. Ce que nous attendions, basé sur notre expérience avec les threads «verts» (non préemptifs), serait que les threads changeraient de contexte moins souvent (réduisant ainsi le temps CPU) si les canaux étaient plus grands. Cependant, nous avons constaté que l'augmentation de la taille des canaux ne change rien à l'exécution. Ce qui semble se passer est que Java décide de changer de threads même si les canaux ne sont pas pleins ou vides (c'est-à-dire même si un thread n'a pas à suspendre), ce qui coûte du temps CPU sans avantage apparent. La modification des priorités Thread ne fait pas de différence notable. Ma question est de savoir s'il y a moyen de persuader Java de ne pas faire de changements de contexte inutiles, mais de bloquer la commutation jusqu'à ce qu'il soit vraiment nécessaire de changer de threads. Y a-t-il un moyen de changer la logique d'envoi de Java? Ou réagit-il à quelque chose auquel je n'ai pas prêté attention ?! Ou existe-t-il d'autres mécanismes d'asynchronisme, par ex. Fabriques de threads, Runnable (s), peut-être même démons (!). La réponse semble être non évidente, car jusqu'à présent, aucun de mes correspondants n'a trouvé de réponse (y compris les deux derniers professeurs de CS). Ou peut-être que je manque quelque chose qui est si évident que les gens ne peuvent pas imaginer que je ne le sache pas ...Commutateurs de contexte Java inutiles

J'ai ajouté le code d'envoi et de réception ici - pas très élégant, mais il semble fonctionner ... ;-) Au cas où vous vous poseriez la question, je pensais que la logique goLock dans 'send' pouvait causer le problème, mais le supprimer temporairement ne faisait aucune différence. J'ai ajouté le code pour envoyer et recevoir ...

public synchronized Packet receive() {

if (isDrained()) { 
    return null; 
} 

while (isEmpty()) { 


    try { 
    wait(); 
    } catch (InterruptedException e) {   
    close(); 
    return null; 

    }  

    if (isDrained()) { 

    return null; 
    } 

} 

if (isDrained()) {  
    return null; 
} 
if (isFull()) { 
    notifyAll(); // notify other components waiting to send 
} 
Packet packet = array[receivePtr]; 
array[receivePtr] = null; 
receivePtr = (receivePtr + 1) % array.length; 
//notifyAll(); // only needed if it was full 
usedSlots--; 

packet.setOwner(receiver); 

if (null == packet.getContent()) { 
    traceFuncs("Received null packet"); 
} else { 
    traceFuncs("Received: " + packet.toString()); 
} 


return packet; 

}

synchronized boolean send(final Packet packet, final OutputPort op) {

sender = op.sender; 

if (isClosed()) { 

    return false; 
} 

while (isFull()) { 


    try { 
    wait(); 
    } catch (InterruptedException e) {   
    indicateOneSenderClosed();  
    return false; 
    } 

    sender = op.sender; 

} 

if (isClosed()) { 

    return false; 
} 

try { 
    receiver.goLock.lockInterruptibly(); 
} catch (InterruptedException ex) { 
    return false; 
} 

try { 
    packet.clearOwner(); 
    array[sendPtr] = packet; 
    sendPtr = (sendPtr + 1) % array.length; 
    usedSlots++; // move this to here 
    if (receiver.getStatus() == StatusValues.DORMANT || receiver.getStatus() == StatusValues.NOT_STARTED) { 
    receiver.activate(); // start or wake up if necessary 
    } else { 
    notifyAll(); // notify receiver 
    // other components waiting to send to this connection may also get 
    // notified, 
    // but this is handled by while statement 
    } 

    sender = null; 
    Component.network.active = true; 
} finally { 
    receiver.goLock.unlock(); 

} 
return true; 

}


merci de demander! J'ai discuté la même question sur le forum Sun, et voici mon dernier message sur ce forum:

Notre meilleure estimation est en ce moment que cet effet résulte de logique de programmation Windows.

Microsoft semble reconnaître que ce domaine a besoin d'une certaine amélioration car il introduit UMS - je cite: « UMS est recommandé pour les applications avec des exigences de haute performance qui ont besoin pour fonctionner efficacement de nombreux threads simultanément sur les systèmes multiprocesseurs ou multicœurs . ... UMS est disponible en commençant par les versions 64 bits de Windows 7 et Windows Server 2008 R2 Cette fonctionnalité n'est pas disponible sur les versions 32 bits de Windows. " Espérons que Java profitera de UMS dans les versions ultérieures de .

Merci pour votre aide!

+0

Quel JDK utilisez-vous? Essayez de faire la même chose sous Linux ... si ça marche mieux, c'est XP. – ReneS

+0

Des nouvelles à ce sujet? Avez-vous trouvé une solution? – ReneS

+0

Cela ne sert à rien que Java utilise les threads OS pour JSE et JEE. Cela signifie que vous êtes à la merci du fonctionnement de votre système d'exploitation. Pour un meilleur contrôle de la commutation de contexte, vous pouvez utiliser un système d'exploitation en temps réel. Cependant, votre problème est peut-être que votre système d'exploitation essaie d'être équitable vis-à-vis des threads de votre processus et que vous avez plus de threads que vous avez de cœurs, il doit donc les échanger. Je dirais que vous avez moins de fil que les noyaux et il devrait changer beaucoup moins. –

Répondre

1

Je suis un peu gêné - il eu tout à coup me cet après-midi que peut-être le réseau dont la performance que j'étais inquiet au sujet était trop simple, comme je l'ai eu que deux processus es, et deux processus eurs. Donc, Windows a peut-être essayé trop dur pour garder les processeurs équilibrés! Je me suis donc demandé ce qui se passerait si je donnais beaucoup de processus à Windows.

I mis en place deux réseaux:

a) 50 Générer des composants d'alimentation 50 composants Jeter - réseau ie hautement parallèle - de sorte que ce 100 fils au total

b) 50 générer des composantes d'alimentation 1 composant Discard - à savoir réseau hautement "canalisé" - donc c'est 51 threads

J'ai couru chacun 6 fois avec une capacité de connexion de 10, et 6 fois avec une capacité de connexion de 100. Chaque exécution a généré un total de 50 * 20 000 paquets d'information, pour un total de 1.000.000 de paquets, et a duré environ 1 minute ..Voici les moyennes des 4 cas: a) avec une capacité de connexion de 10 - 59.151 secs. a) avec une capacité de connexion de 100 - 52.008 secs. B) avec une capacité de connexion de 10 à 76,745 secondes. b) avec une capacité de connexion de 100 - 60,667 secs. Il semble donc que la capacité de connexion fasse la différence! Et, il semble que JavaFBP fonctionne assez bien ... Je m'excuse d'être un peu hâtif - mais peut-être que nous avons tous pensé un peu plus au multithreading dans une machine multicœur ... ;-)

Encore une fois, et merci à tous ceux qui ont contribué à ce sujet!

0

Désolé, si c'est un total faux, mais je suis assez sûr que Java ne fait plus de threads verts depuis Java 1.1. Au moins Wikipedia le dit aussi. Cela vous limiterait à utiliser les priorités, mais dans la plupart des cas, je ne pouvais pas non plus obtenir d'amélioration notable des performances.

+0

Non, je suis d'accord - je n'ai pas fait de progrès de cette façon! Y a-t-il une alternative aux priorités? –

4

Les threads verts sont partis (peut-être que Solaris le supporte encore mais j'en doute). De plus, Java ne change pas de threads, le système d'exploitation le fait. La seule chose que fait Java est de signaler au système d'exploitation qu'un thread est inactif/attend/bloque en utilisant les fonctions du système d'exploitation. Donc, si votre programme atteint un point de synchronisation, Thread.wait/sleep, il signalera qu'il n'a plus besoin du cpu.En outre, le système d'exploitation conserve les tranches de temps et supprime le processeur d'un thread, même s'il peut toujours être exécuté lorsque d'autres threads attendent le processeur.

Pouvez-vous publier plus de code ici?

+0

Juste oublié de mentionner, l'acquisition de mémoire est toujours un moment, lorsque le système d'exploitation pourrait pousser votre thread sur le processeur ... – ReneS

+0

Y at-il un moyen d'augmenter la longueur des tranches de temps du système d'exploitation? –

+0

Oui, cela dépend de votre système d'exploitation et du mode dans lequel il fonctionne. Par exemple, le serveur Ubuntu exécute d'autres tranches que Ubuntu Desktop. (demandez à severfault.com). Mais essayez d'abord de lier votre processus à un processeur et vérifiez s'il fonctionne mieux. – ReneS

Questions connexes