Je fais un projet où j'ai besoin de tous les appels d'API pour prendre moins de 1s mais je suis confronté à un problème avec le premier appel à chaque route qui est plus lent que les suivants.
Actuellement, le premier appel à / login prend 3,6 secondes et les suivants prennent 170 ms et même pour toutes les autres routes.
J'ai découvert -XX:+TraceClassLoading
qu'en utilisant cela lors du premier appel, les classes étaient chargées en mémoire et cela causait le problème de performances.
Cependant, je n'ai pas trouvé de moyen facile de charger toutes les classes au démarrage et pour chaque nouveau service, j'ai besoin d'ajouter un appel de préchauffage dans un ApplicationRunner.
Quelqu'un a-t-il une solution pour charger automatiquement les classes d'une application SpringBoot ou réchauffer toutes ses routes?
invokedynamic
et nous savons que la résolution est lente au premier appel pour celles-ci (nous avons des dizaines de milliers de ces appels, qui sans ce premier appel s'accumulent à des dizaines de secondes).Réponses:
Le chargement des classes de Java est paresseux. Cela signifie qu'une classe n'est chargée par la JVM que lorsqu'elle en a besoin et si elle le doit.
Si vous souhaitez le forcer à charger les classes avec impatience, il vous suffit de les référencer. Une façon de le faire consiste à parcourir le contenu du pot ou les fichiers de classe pour obtenir les noms de classe, puis les utiliser pour appeler
Class.forName(className)
.De plus, si le temps de démarrage et les performances sont très importants pour votre cas d'utilisation, vous pouvez envisager des solutions de compilation à l' avance comme GraalVM , ou réduire le seuil de compilation de JIT (
-XX:CompileThreshold
).la source
JIT
n'a vraiment aucun sens lors des premières invocations.GraalVM
c'est bien, mais s'il vous plaît jetez un œil au nombre de problèmes qu'il a dans github: dès que vous passez d'un projet de bac à sable à quelque chose de plus grand (je regarde votre réflexion, principalement), vous aurez mal, au moins. mon point est: le passage à GraalVM n'est pas un simple claquement de doigts.Pour moi, la seule option viable que vous avez est
class data sharing
, répartie sur JEP 310 , JEP 341 et JEP 350 , mais cela nécessite probablement Java-13. Nous testons cela en interne sur mon lieu de travail (surtout pour le plaisir, je ne vais pas mentir) et les résultats semblent bons jusqu'à présent.L'autre option appelle vos points de terminaison au démarrage de l'application - si c'est une option. Encore une fois, il est pour nous par exemple: nous les appelons avec des données fictives quelques centaines de fois pour se réchauffer le code. Mais, en même temps, nous avons des services où cela serait impossible - c'est pourquoi l'exploration de
CDS
trop.la source