web-dev-qa-db-fra.com

Écriture à faible latence Java

Existe-t-il des techniques spécifiques à Java (des choses qui ne s'appliqueraient pas au C++) pour écrire du code à faible latence, en Java? Je vois souvent Java rôles à faible latence et ils demandent une expérience d'écriture de Java à faible latence - ce qui semble parfois un peu un oxymore.

La seule chose à laquelle je pourrais penser est l'expérience avec JNI, l'externalisation des appels d'E/S vers du code natif. Peut-être aussi en utilisant le modèle de perturbateur, mais ce n'est pas une technologie réelle.

Existe-t-il des Java astuces spécifiques pour écrire du code à faible latence?

Je suis conscient qu'il existe une spécification en temps réel Java Spec, mais j'ai été averti en temps réel n'est pas la même chose qu'une faible latence ....

32
user997112

En plus de commentaires de Martijn j'ajouterais:

  1. Réchauffez votre JVM. Le bytecode démarre commence à être interprété pour Hotspot puis est compilé sur le serveur après 10 000 observations . La compilation à plusieurs niveaux peut être un bon point d'arrêt.

  2. Le chargement de classe est un processus séquentiel qui implique IO sur le disque. Assurez-vous que toutes les classes de vos flux de transactions principaux sont chargées à l'avance et qu'elles ne sont jamais expulsées de la génération de perm.

  3. Suivez le " Single Writer Principle " pour éviter les conflits et les implications de la loi de Little sur l'effet de file d'attente, et étudiez la loi d'Amdhal pour savoir ce qui peut être parallèle et cela en vaut-il la peine.

  4. Modélisez votre domaine d'activité et assurez-vous que tous vos algorithmes sont O(1) ou au moins O (log n). C'est probablement la plus grande cause de problèmes de performances dans mon expérience. Assurez-vous que vous avez des performances tests pour couvrir les principaux cas.

  5. Faible latence en Java ne se limite pas à Java. Vous devez comprendre toute la pile sur laquelle votre code s'exécute. Cela impliquera le réglage du système d'exploitation, la sélection du matériel approprié, le réglage du logiciel du système et des pilotes de périphérique pour ce matériel.

  6. Être réaliste. Si vous avez besoin d'une faible latence, ne l'exécutez pas sur un hyperviseur. Assurez-vous que vous disposez de suffisamment de cœurs pour tous les threads qui doivent être à l'état exécutable.

  7. Les échecs de cache sont votre plus grand coût aux performances. Utilisez des algorithmes compatibles avec le cache et définissez l'affinité pour les cœurs de processeur avec l'ensemble de tâches ou numactl pour une JVM ou JNI pour des threads individuels.

  8. Envisagez une JVM alternative comme Zing d'Azul avec un garbage collector sans pause.

  9. Plus important encore, impliquez quelqu'un dans l'expérience. Cela vous fera gagner beaucoup de temps à long terme. Prise sans vergogne :-)

Le temps réel et la faible latence sont des sujets distincts, bien que souvent liés. En temps réel, il s'agit d'être plus prévisible que rapide. D'après mon expérience, les JVM en temps réel, même celles en temps réel, sont plus lentes que les JVM normales.

38
Martin Thompson

Il y a un tas de choses à savoir oui. Je suis en Crète en ce moment avec un accès net limité donc ce sera (assez) court. De plus, je ne suis pas un expert en faible latence, mais plusieurs de mes collègues en jouent un dans la vraie vie :-).

  1. Vous devez apprécier la sympathie mécanique (un terme inventé par Martin Thompson ). En d'autres termes, vous devez comprendre ce que fait votre matériel sous-jacent. Il est très important de savoir comment les processeurs chargent les lignes de cache, quelle est leur bande passante en lecture/écriture, la vitesse de la mémoire principale et bien plus encore. Pourquoi? Parce que vous devrez expliquer comment votre code source Java affecte le système d'exploitation/matériel via la JVM d'exécution. Par exemple, la façon dont vos variables de champ sont présentées dans votre code source provoque la ligne de cache expulsions (vous coûte ~ 150 cycles d'horloge), hmmm ... :-).

  2. En général, vous voulez des algorithmes et des E/S sans verrouillage. Même l'application simultanée la plus bien conçue (qui utilise des verrous) risque de se bloquer, le blocage à faible latence est généralement mauvais :-).

  3. Comprendre l'allocation d'objets et le garbage collection. C'est un sujet énorme, mais fondamentalement, vous voulez éviter les pauses du GC (souvent causées par la nature Stop the World de diverses collections GC). Les collectionneurs GC spécialisés comme le collecteur Azul peuvent dans de nombreux cas résoudre ce problème pour vous dès le départ, mais pour la plupart des gens, ils doivent comprendre comment régler les GC Sun/Oracle (CMS, G1, etc.).

  4. Le Hotspot JIT est vraiment incroyable. En savoir plus sur ses optimisations, mais de manière générale toutes les bonnes OO techniques (encapsulation, petites méthodes, autant de données immuables que possible) permettront à JIT d'optimiser, vous donnant les types de niveaux de performance qui un code C/C++ bien conçu vous donne.

  5. Architecture globale du système. Soyez conscient du réseau, de la façon dont les machines sont colocalisées, si vous êtes connecté au central via une fibre, etc., etc.

  6. Soyez conscient de l'impact de la journalisation. la journalisation binaire ou l'utilisation d'une sortie codée que vous pouvez analyser hors ligne est probablement une bonne idée.

Dans l'ensemble, je recommande fortement de continuer Kirk Pepperdine's Java Performance Tuning course [Disclaimer: j'enseigne ce cours moi-même, donc je suis biaisé]. Vous aurez une bonne couverture des différents aspects de la machine virtuelle Java et de son impact sur le fonctionnement et le matériel sous-jacents.

PS: J'essaierai de revisiter cela plus tard et de le ranger un peu.

23
Martijn Verburg