Mise à jour
Mike a récemment créé et publié un merveilleux profileur léger pour LuaJIT, que vous pouvez trouver à l'adresse suivante ici .
Mise à jour
Le wiki a gagné quelques pages supplémentaires dans ce domaine, en particulier celui-ci qui détaille des éléments supplémentaires non mentionnés dans la réponse originale, et qui est basée sur une poste de liste de diffusion par Mike.
LuaJIT a très récemment lancé son propre wiki et liste de diffusion et avec de telles choses viennent beaucoup, beaucoup plus de gemmes sur l'accélération du code pour LuaJIT.
Pour l'instant, le wiki est plutôt mince (mais il est toujours à la recherche de personnes pour l'enrichir), mais une excellente page a été ajoutée récemment. une liste des fonctions de la JNI . Les fonctions JNI provoquent l'abandon du JIT et le retour à l'interprète. Il est donc évident qu'il faut éviter autant que possible les fonctions JNI sur le hotpath, en particulier dans les boucles.
Quelques sujets d'intérêt de la liste de diffusion :
Et pour répéter ce qui est dit plus bas (parce que c'est utile), -jv
est le meilleur outil pour l'optimisation des performances, il doit également être votre première étape pour le dépannage.
Réponse originale
Je doute que vous trouviez beaucoup de choses à ce sujet, principalement parce que LJ2 est encore en version bêta, et donc la plupart des profils sont faits naïvement car il n'y a pas de crochets de débogage pour les choses spécifiques à LJ2 comme l'enregistreur de traces.
D'un point de vue positif, le nouveau module FFI permet des appels directs aux timers haute résolution (ou aux API de profilage comme VTune/CodeAnalyst), vous pouvez profiler de cette façon, mais tout ce qui est plus nécessite des extensions au noyau JIT de LJ2, ce qui ne devrait pas être trop difficile, car le code est clair et commenté.
Un des paramètres de la ligne de commande de l'enregistreur de traces (pris à partir de ici ) :
Les commandes -jv et -jdump sont des modules d'extension écrits en Lua. Elles sont principalement utilisées pour déboguer le compilateur JIT lui-même. Pour une description de leurs options et du format de sortie, veuillez lire le document au début de leur source. Ils peuvent être trouvés dans le répertoire lib de la distribution des sources ou installés sous le répertoire jit ou installés sous le répertoire jit. Par défaut, celui-ci est /usr/local/share/luajit-2.0.0-beta8/jit sur les systèmes POSIX.
ce qui signifie que vous pouvez utiliser le code du module des commandes pour former la base d'un module de profilage pour LuaJIT 2.
Mise à jour
Avec la mise à jour de la question, il est un peu plus facile d'y répondre. Commençons donc par la source, LuaJIT.org :
Avant d'optimiser manuellement un code, il est toujours bon de vérifier les ressources de réglage de l'optimisation du JIT :
Compilation
De la Running nous pouvons voir toutes les options pour définir les paramètres du JIT, pour l'optimisation, nous nous concentrons sur la page -O
option. Immédiatement, Mike nous dit que l'activation de toutes les optimisations a un impact minimal sur les performances, alors assurez-vous d'exécuter en -O3
(qui est maintenant la valeur par défaut), donc les seules options ici ayant une réelle valeur pour nous sont les seuils JIT et Trace.
Ces options sont très spécifiques au code que vous écrivez, il n'y a donc pas de "paramètres optimaux" génériques en dehors des valeurs par défaut, mais il va sans dire que si votre code comporte de nombreuses boucles, expérimentez avec le déroulement des boucles et chronométrez le temps d'exécution (mais videz le cache entre chaque exécution si vous recherchez des performances de démarrage à froid).
-jv
est également utile pour éviter de connaître questions/"fallbacks qui provoquera le renflouement de l'ITC.
Le site lui-même n'offre pas beaucoup d'informations sur la façon d'écrire un code meilleur ou plus optimisé, à l'exception de quelques petites informations dans la section "Code". Tutoriel FFI :
Mise en cache des fonctions
La mise en cache des fonctions est un bon moyen d'améliorer les performances en Lua, mais il est moins important de s'y intéresser en LuaJIT, car le JIT effectue lui-même la plupart de ces optimisations. est Il est important de noter que la mise en cache des fonctions FFI C est mauvais il est préférable de mettre en cache l'espace de noms dans lequel ils résident.
Un exemple de la page :
mauvais :
local funca, funcb = ffi.C.funcb, ffi.C.funcb -- Not helpful!
local function foo(x, n)
for i=1,n do funcb(funca(x, i), 1) end
end
bon :
local C = ffi.C -- Instead use this!
local function foo(x, n)
for i=1,n do C.funcb(C.funca(x, i), 1) end
end
Problèmes de performance de FFI
le site Statut La section détaille diverses constructions et opérations qui dégradent les performances du code (principalement parce qu'elles ne sont pas compilées, mais utilisent la VM de secours à la place).
Nous passons maintenant à le site source de toutes les gemmes LuaJIT, le fichier Liste de diffusion Lua :
-
Éviter les appels C et les appels Lua de la JNI dans les boucles Si vous voulez que le traceur LJ2 se mette en marche et donne un feedback utile, vous devez éviter les fonctions NYI(not yet implement) ou les appels C où le compilateur de trace ne peut pas aller. Donc si vous avez des petits appels C qui peuvent être importés dans Lua et qui sont utilisés dans des boucles, importez-les, au pire ils pourraient être '6% plus lents' que l'implémentation du compilateur C, au mieux ils seront plus rapides.
-
Utiliser les tableaux linéaires sur les ipairs Selon Mike, la méthode pairs/suivants sera toujours plus lente que les autres méthodes (il y a aussi un petit détail sur la mise en cache des symboles pour le traceur).
-
Évitez les boucles imbriquées chaque niveau d'imbrication nécessite un passage supplémentaire pour le traçage, et sera légèrement moins optimisé, évitez spécifiquement les boucles internes avec des itérations inférieures.
-
Vous pouvez utiliser des tableaux à base 0 : Mike indique ici que LuaJIT n'a pas de pénalité de performance pour les tableaux basés sur 0, contrairement à Lua standard.
-
Déclarer les locals dans la portée la plus interne possible Il n'y a pas de véritable explication, mais je crois que cela a à voir avec l'analyse de la vivacité de la SSA. Il contient également des informations intéressantes sur la façon d'éviter un trop grand nombre de locaux (ce qui casse l'analyse de la vivacité).
-
Évitez les nombreuses petites boucles Cela perturbe l'heuristique de déroulement et ralentit le code.
Petits détails :
Des outils de profilage sont disponibles pour le Lua normal, cependant, il y a un projet plus récent qui est officiellement compatible avec LuaJIT (je doute qu'il prenne en compte les fonctionnalités de LuaJIT cependant), luatrace . Le wiki Lua dispose également d'une page sur conseils d'optimisation pour Lua normal, il faudrait tester leur efficacité sous LuaJIT (la plupart de ces optimisations sont probablement déjà réalisées en interne), cependant, LuaJIT utilise toujours la GC par défaut, ce qui en fait un domaine où les gains d'optimisation manuelle peuvent encore être importants (jusqu'à ce que Mike ajoute la GC personnalisée qu'il a mentionné faire ici et là).
Le code source de LuaJIT contient quelques paramètres permettant de manipuler les éléments internes du JIT. Cependant, ces paramètres nécessitent des tests approfondis pour être adaptés à votre code spécifique, en fait, il pourrait être préférable de les éviter complètement, surtout pour ceux qui qui ne sont pas familiers avec les internes du JIT.