Écriture de Java à faible latence [fermé]

30

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 des rôles Java à faible latence et ils demandent de l'expérience en écriture Java à faible latence - ce qui semble parfois un peu 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 conseils spécifiques à Java pour écrire du code à faible latence?

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

user997112
la source
ne créez pas trop d'objets qui pourraient déclencher un cycle de collecte serait ma conjecture
ratchet freak
@ratchet, je suppose que tout ce qui concerne le réseau ou le disque serait également JNI?
user997112
Pour d'autres liens et présentations, vous pourriez être intéressé par le groupe d'utilisateurs Java de performance plus.google.com/u/1/communities/107178245817384004088
Peter Lawrey
J'ajouterais en utilisant sun.misc.Unsafe, directement ou indirectement est utile. De nombreuses méthodes dangereuses sont traitées comme intrinsèques, ce qui signifie qu'elles sont remplacées par du code machine, ce qui évite tout JNI.
Peter Lawrey
La principale technique consiste à éviter complètement les frais généraux du GC. Vous pouvez en savoir plus à ce sujet dans cet article Développement Java sans GC
rdalmeida

Réponses:

35

En plus des 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 des E / S sur disque. Assurez-vous que toutes les classes de vos principaux flux de transactions sont chargées à l'avance et qu'elles ne sont jamais expulsées de la génération de perm.

  3. Suivez le " principe du rédacteur unique " 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 disposez de tests de performances pour couvrir les principaux cas.

  5. La 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 logiciel du système de réglage et les 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. Considérez 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.

Martin Thompson
la source
2
+1 pour une excellente réponse. En tant que personne intéressée par le traitement des messages télévisés comme celui-ci, c'est un excellent point de départ pour la recherche.
mcfinnigan du
23

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 des expulsions de ligne de cache (cela 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 d'une manière générale, toutes les bonnes techniques OO (encapsulation, petites méthodes, autant de données immuables que possible) permettront à JIT de s'optimiser, vous donnant le type de niveaux de performance que vous offre un code C / C ++ bien conçu.

  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 suivre le cours de réglage des performances Java de Kirk Pepperdine [Avertissement: j'enseigne ce cours moi-même, donc je suis partial]. Vous bénéficierez d'une bonne couverture des différents aspects de la JVM et de son impact sur le fonctionnement et le matériel sous-jacent.

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

Martijn Verburg
la source
Ce serait vraiment bien si ceux qui ont de l'expérience avec Mechanical Sympathy pouvaient partager certaines des astuces pour détecter quand une frontière donnée a été franchie.
J'ai fait un ping sur Twitter pour essayer d'obtenir les vrais experts en :-)
Martijn Verburg
Cool, Martin Thompson est intervenu, vaut la peine de suivre ses conseils sur les miens.
Martijn Verburg