8
votes

CPU d'étranglement à partir de Java

J'ai vu de nombreuses questions dans ce forum (et d'autres) avec le même titre, mais aucun d'entre eux ne semblait aborder exactement mon problème. Ça y est: J'ai une JVM qui mange tout le processeur sur la machine qui l'héberge. Je voudrais l'accélérer, mais je ne peux pas compter sur aucun outil d'étranglement / technique externe à Java, car je ne peux pas faire d'hypothèses sur l'endroit où ce VM sera exécuté. Ainsi, par exemple, je ne peux pas utiliser l'affinité de processeur car si la machine virtuelle est exécutée sur un Mac, le système d'exploitation ne rendra pas l'affinité de processus disponible.

Ce dont j'aurais besoin, c'est une indication de savoir si des moyens existent dans Java pour s'assurer que le fil ne prend pas la CPU complète.

Je tiens à pointer tout de suite que je ne peux pas utiliser de techniques basées sur des exécutions et des pauses de processus alternés, comme suggéré dans certains forums, car le fil doit générer des valeurs de manière continue.

Idéalement, j'aimerais que cela signifie, par exemple, définir une certaine priorité ou une priorité de filetage, ou de la casquette du pourcentage de CPU consommé.

Toute aide serait très appréciée.


10 commentaires

Vous voulez savoir s'il y a une API dans Java qui indique à la JVM de permettre à d'autres threads / applications de fonctionner? Le plus proche que vous obtiendrez, c'est thread.yield () ou setPRiority () - mais ces API n'ont pas de garanties.


thread.yield () ne résoudra pas son problème. Il ne ralentira pas le Javora à tout @noahz.


Quelle est votre définition de « ralentir la machine virtuelle Java vers le bas? » Vous vous rendez compte que la machine virtuelle Java compile finalement votre bytecode aux instructions de la machine, non? À moins que votre code contient des instructions pour le faire tourner lentement (par exemple Thread.sleep () ), vous ne pouvez pas le faire « courir plus lentement » via les paramètres JVM.


Merci a tous. Il ne ralentit pas la machine virtuelle Java vers le bas ce que je veux, je préférerais vouloir un moyen de définir une priorité qui est reconnue en dehors de la machine virtuelle Java. Lorsque vous définissez la priorité d'un fil, que la priorité est valable au sein de la machine virtuelle Java seulement et non à l'extérieur. Idéalement, je aurais besoin quelque chose de similaire, mais reconnu au niveau des processus du système. Espère que je parviens à me expliquer correctement :-)


Connecté: Stackoverflow.com/Questions/1202184/...


J'aurais pensé que une sorte de mise en pause intermittente doit participer, à moins peut-être que vous voulez limiter précisément le nombre de cœurs de processeurs autorisés à exécuter votre programme. Pourquoi voulez-vous accélérer le programme - pour économiser l'énergie ou pour libérer la puissance du processeur pour d'autres applications?


Vous pouvez examiner le nombre de processeurs disponibles et limiter vos tailles de piscine de thread en fonction de ce numéro.


@assylie: J'avais examiné cette question, mais les réponses à ce sujet tendent principalement à aborder la question liée à la mémoire, au lieu de la CPU. En outre, les méthodes suggérées sont basées sur la pause de l'application, ce qui n'est pas ce que je voulais. En fait, dans ma question, j'ai placé un avertissement de non-responsabilité indiquant que je ne suis pas intéressé par des techniques basées sur des exécutions et des pauses à cet effet :-)


@JIMPANZEE: J'aimerais trouver un moyen de vous assurer que la JVM prend autant de processeur que si la CPU est réellement disponible, laissant ainsi à des processus système plus importants lorsqu'il doit être récupéré.


La seule chose à laquelle je passe est de tenter de surveiller l'utilisation du système de la CPU de votre programme, puis de l'utiliser pour déterminer le nombre de millisecondes à thread.sleep () dans votre boucle, si du tout.


5 Réponses :


6
votes

Ce dont j'aurais besoin, c'est une indication de savoir si des moyens existent dans Java pour s'assurer que le fil ne prend pas la CPU complète.

Il n'y a aucun moyen que je sache de le faire dans Java, à l'exception de la réglage de votre application pour utiliser moins de processeur.

  • Vous pouvez mettre quelques thread.sleep (...); appelle dans vos méthodes de calcul. Un profileur aiderait à vous montrer les boucles / méthodes chaudes / etc.
  • Forking Moins de fils affecterait également la CPU utilisée. Se déplaçant vers des piscines de tailles fixes ou une réduction du nombre de fils dans vos piscines.
  • Ce n'est peut-être pas un processeur qui est le problème, mais d'autres ressources. Regardez votre bande passante Io par exemple. Ralentissement de votre réseau ou de votre disque Les lectures / écritures de votre disque peuvent restaurer votre serveur à un bon fonctionnement.

    de l'extérieur du JVM, vous pouvez utiliser la commande ~ Unix Nice pour affecter la priorité de l'exécution de JVM pour ne pas dominer le système. Cela lui donnera la CPU si disponible mais laissera les autres applications d'obtenir plus de la CPU.


11 commentaires

Merci Gray. Je sais pertinemment que mon problème est avec CPU et pas d'autres ressources. En outre, mon application est mono-thread, il est un fil simple qui génère et envoie des messages. Tout se fait dans le thread principal, il n'y a pas threadpools ni fourchettes d'aucune sorte.


@Diferdin afin que votre application s'exécute sur une seule machine à noyau?


Comme mon post mentionne @Diferdin, je envisagerais d'utiliser agréable pour réduire la priorité du système d'exploitation du processus. Cela donnera plus de ressources à d'autres applications système s'il y a quelque chose. Donc, cela consommera de la CPU mais ne domine pas.


Juste FYI - Même si votre application est une seule fois filetée, sauf si vous utilisez un outil tel que CPUSET Le système d'exploitation pourrait le déplacer dans différents cœurs.


@Gray: merci! Avez-vous un pointeur où je peux avoir des informations sur ce que c'est bien? (En fait, j'ai pensé dans votre réponse originale c'était une faute de frappe! :-))


@noahz: Je crois que ce que vous mentionnez est appelé affinité du processeur et je le mentionne dans mon email. Il est exactement pourquoi je ne peux pas / ne veulent pas utiliser des moyens externes à Java, je peux faire aucune hypothèse quant à l'endroit où cette classe sera exécutée et certains systèmes d'exploitation (par exemple MacOS) ne vous permettra pas d'affinité tune


@Diferdin Dans ce cas, vous ne pouvez probablement pas faire d'hypothèses sur ce que JVM est utilisé, car ils ont chacune des caractéristiques différentes. Les seules garanties que vous obtenez sont ce qui est dans le Java SDK (si vous utilisez Java Standard Edition), la spécification de langue Java et la spécification de la machine virtuelle Java (qui décrit le code d'octets, etc. Caractéristiques du fournisseur JVM exclusivement). Ainsi, comme d'autres l'ont souligné, vous allez devoir prendre des responsabilités dans votre code et «l'accélérez» vous-même.


@noahz: pas tout à fait vrai :-) Nous pouvons vous recommander un type VM et / ou la version, mais nous devons garantir ce que nous recommandons des travaux sur tous les systèmes d'exploitation ...


Salut, j'ai accepté ma réponse, au fond de ce fil, comme tous les autres ne répondent pas pleinement mon problème.


Oh désolé @Diferdin. N'a pas vu ça. Accepter le vôtre, c'est bien, même si je ne vois aucune information dans la vôtre qui n'est pas dans ma réponse. J'ai recommandé le gentil par exemple. Mais peu importe.


@Gray laissez-moi reformuler. J'ai fini par utiliser bien parce qu'il n'y avait rien vraiment comme je le voulais. Alors oui - j'ai pris de belles de votre réponse, mais je voulais préciser que ce n'était pas mon premier choix. Merci de quelque manière que ce soit! :-)



2
votes

Je suppose que vous voulez quelque chose de plus fiable que définir les priorités des threads ?

Si vous souhaitez une exécution étranglée d'un code générant en permanence des valeurs, vous devez rechercher le travail le ou les threads, et codez dans votre propre minuterie. Par exemple, le java.util.timer permet Exécution de planification à un taux fixe .

Toute autre technique consumera toujours autant de processeur que possible (1 noyau par thread, en supposant qu'aucun verrouillage empêche l'exécution simultanée) lorsque le planificateur n'a pas d'autres tâches pour hiérarchiser avant le vôtre.


4 commentaires

+1 Je suis tout à fait d'accord avec cette approche. Bien sûr, l'OP doit comprendre quelle partie du code prend beaucoup de processeur, alors je recommanderais également un profileur d'une sorte. De plus, comme il n'est probablement pas possible d'obtenir la charge de la CPU, l'approche devra être accordée afin qu'elle puisse être modifiée sur différents systèmes.


Avec les commentaires de suivi de l'OP, je pense que le cœur de sa question est le suivant: "Le JVM peut être configuré comme en tant que bac à sable pour diverses choses, y compris le système de fichiers, le réseau, etc. La JVM peut également fournir un bac à sable qui limite même mal Impact du programme écrit sur le (s) processeur (s) du système hôte (s). Idéalement, cela doit être contrôlable à une manière non spécifique à la mise en œuvre non JVM, par exemple JMX. "


J'accepte dans une certaine mesure; J'aimerais avoir un mécanisme basé sur la priorité, mais le mécanisme de priorité de filetage Java standard n'a de validité que dans la JVM, alors que j'aurais besoin de quelque chose de similaire mais avec la validité au niveau du système d'exploitation / du noyau. Ce que j'aimerais idéalement, c'est un moyen de dire à la JVM d'utiliser une CPU complète lorsqu'il est disponible et de soulager certaines lorsque d'autres processus système, éventuellement plus importants, le besoin.


@Diferdin, qui devrait être la manière dont un programme régulier (sans code spécial pour la gestion de la priorité, etc.) s'exécutant sur un comportement JVM. Si le JVM n'expose pas ce comportement, je dirais que votre système d'exploitation ne fait pas son travail.



1
votes

Le détail est tout simplement que vous avez dit « doit générer des valeurs en continu », et si cela, à l'extrême, est vrai, alors la saturation du processeur est en fait l'objectif.

Mais, si vous définissez « en continu » en tant que valeurs X par seconde, alors il y a de la place au travail.

Parce que vous pouvez exécuter votre processus à 100% du CPU, mesurer le nombre de valeurs au fil du temps, et si vous trouvez qu'il est génère plus de valeurs que nécessaire (plus de X / sec), vous pouvez maintenant insérer des pauses pour le processus selon le cas jusqu'à ce que le taux de valeur atteint votre objectif souhaité.

Le plan étant de surveiller en permanence et d'ajuster les pauses pour maintenir votre taux de valeur au fil du temps. Ensuite, votre processus prendra autant de CPU que nécessaire pour répondre à vos valeurs / objectif sec.

Addenda:

Si vous avez une référence de valeurs / sec que vous êtes satisfait, alors interposant sommeils donnera « toute la priorité nécessaire » aux autres applications, mais toujours maintenir votre débit. Si, d'autre part, vous n'avez pas besoin solide, qui est l'exigence est « courir aussi vite que possible quand rien ne fonctionne autre, sans exigence réelle pour les résultats si un autre processus domine la CPU », puis qui est vraiment un problème du noyau du système d'exploitation hôte, et non quelque chose de la machine virtuelle Java a un mécanisme portable directement, à l'adresse.

Sur les systèmes Unix, vous avez la belle (1) commande pour régler la priorité processus (pas thread), et Windows a son propre mécanisme. Avec ces commandes, vous pouvez frapper la priorité de votre processus Java juste au-dessus ( « process », la valeur par défaut qui fonctionne toujours quand rien ne fonctionne autre) « inactif ». Mais il est spécifique de la plate-forme, car cela est un problème spécifique de la plate-forme en soi. Cela pourrait bien être géré par des scripts spécifiques de plate-forme de lancer votre programme Java (ou même un lanceur Java qui détecte la plate-forme et « fait la bonne chose » avant d'exécuter votre code réel).

La plupart des systèmes vous permettra de réduire vos propres priorités de processus, mais peu vous laisser lever à moins que vous êtes un admin / super-utilisateur ou tout ce qui est le rôle approprié pour votre système d'exploitation hôte.


1 commentaires

Merci, et si tel est le cas, laissez-moi reformuler: j'aimerais JVM pour utiliser autant de processeur que possible, mais en relâchant des processus système autres, plus importants, le besoin



0
votes

Vérifiez si vous avez des "boucles serrées" dans votre code.

while (true) {
  if (object.checkSomething()) {
    ...
  }
  try {
    Thread.sleep(100);
  } catch (InterruptedException e) {
    // purposefully do nothing
  }
}


3 commentaires

Bon point, mais ce serait probablement plus facile et plus sûr d'utiliser un profileur de quelque sorte. Vous ne voulez pas finir par "optimiser" quelque chose qui n'a pas besoin d'être optimisé, éventuellement aggraver les choses. Bien que la réponse soit pour une langue et une technologie différentes, je pense que les concepts sont les mêmes: Stackoverflow.com/Questtions/10800372/...


La suppression des boucles serrées n'est pas une optimisation. La suppression des boucles serrées est la correction de la mauvaise conception. Considérez-le d'un bogue de performance, provoqué par des personnes qui pensent que des bugs comme des choses qui affectent leur code de remplir.


Je suis d'accord avec vous sur la définition des bogues et la correction de la mauvaise conception, mais un bon profileur doit toujours être préférable.



-1
votes

fil vraiment intéressant. J'ai découvert Java ne fournit pas de moyens pour faire ce que je veux faire, et la seule façon de le faire est de à l'extérieur la machine virtuelle Java. J'ai fini avec belle pour modifier la priorité d'ordonnancement dans mon test (Linux) environnement, auront encore besoin de trouver quelque chose de similaire pour les systèmes d'exploitation à base GAGNER.

L'intervention de chacun a été très apprécié.


0 commentaires