Technologie Sortie de LuaJIT 2.0.0

Posté par (page perso) . Édité par Benoît, Nÿco, baud123, Benoît Sibaud, tuiu pol et Florent Zara. Modéré par patrick_g. Licence CC by-sa
Tags : aucun
27
12
nov.
2012
Technologie

Le 12 novembre, LuaJIT 2.0.0 a été publié par Mike Pall, après 3 ans de développement et 11 versions bêta. LuaJIT est un interpréteur et compilateur Just In Time pour le langage Lua. L'interpréteur est une machine à registre (et non à pile, comme la JVM ou .NET) avec 93 opcodes.

LuaJIT est compatible, aussi bien au niveau API que ABI, avec Lua 5.1, ce qui signifie que, non seulement tout code source Lua 5.1 fonctionne sur LuaJIT, mais également tout module d'extension natif compilé pour Lua 5.1.

C'est une réécriture complète par rapport à la version 1.x, qui était jusqu'à ce jour la version stable destinée à la production, mais qui ne prenait en charge que l'architecture x86 et n'offrait pas de module FFI (Foreign Function Interface).

LuaJIT est disponible pour les plateformes classiques (Linux, BSD, Mac OS X, Windows), mais aussi pour des plateformes mobiles ou de jeux : Android, iOS, PS3. LuaJIT permet la compilation croisée, il est donc également disponible sur des environnements visant l'embarqué, comme Buildroot.

LuaJIT prend en charge les architectures suivantes : x86, x64, ARM, PPC, MIPS. Toutefois, le mode JIT ne fonctionne pas sur certaines plateformes, comme par exemple iOS ou Windows 8/ARM.

Bref historique des beta

Releases of LuaJIT

  • bêta1 : Première publication, le 31 octobre 2009.
  • bêta3 : Ajout de l'architecture x64.
  • bêta6 :
    • Ajout du port PowerPC/e500v2.
    • Introduction du module FFI (_Foreign Function Interface_).
  • bêta7 :
    • Ajout de l'architecture ARMv5.
    • Ajout du mode dual-number.
  • bêta8 : Ajout d'un format pour sauvegarder et charger le bytecode généré. Note: ce format est différent de celui de l'interpréteur Lua standard.
  • bêta9 : Le module FFI gère les callbacks.
  • bêta10 : Ajout de l'architecture MIPS.
  • bêta11 :
    • Introduction du goto provenant de Lua 5.2.
    • Prise en charge de l'architecture ARMv7 et VFPv3 (FPU).
    • Ajout du port PS3.
    • Introduction d'un minilua (basé sur Lua 5.1.5) qui permet de générer, au moment de la construction, tous les fichiers sources dépendant des différentes architectures.

Un exemple de code

Calcul de factorielle :

local function factorial (n)
    local a = 1
    for i = 1, n do
        a = a * i
    end
    return a
end

for a = 1, 1000 do
    print(factorial(7))
end

Le mode interpréteur avec son bytecode :

$ luajit -b -l fact.lua
-- BYTECODE -- fact.lua:1-7
0001    KSHORT   1   1
0002    KSHORT   2   1
0003    MOV      3   0
0004    KSHORT   4   1
0005    FORI     2 => 0008
0006 => MULVV    1   1   5
0007    FORL     2 => 0006
0008 => RET1     1   2
...

La boucle de 1000 permet de mettre en route le mode JIT (ici pour du x86) :

$ luajit -jdump fact.lua
...
---- TRACE 1 mcode 115
...
->LOOP:
b77cefe0  xorps xmm6, xmm6
b77cefe3  cvtsi2sd xmm6, edi
b77cefe7  mulsd xmm7, xmm6
b77cefeb  add edi, +0x01
b77cefee  cmp edi, eax
b77ceff0  jle 0xb77cefe0    ->LOOP
b77ceff2  jmp 0xb77c7014    ->3
---- TRACE 1 stop -> loop
    ...

Le mode dual-number

Lua n'a qu'un type number, l'interpréteur standard utilise les double du C pour gérer des nombres entiers ou flottants. Le mode dual-number permet de sous-typer dynamiquement, entre entier et flottant. C'est particulièrement utile pour certains processeurs ARM qui n'ont pas de FPU et dont le traitement des flottants est réalisé par des routines logicielles.

Le Module FFI (Foreign Function Interface)

Ce module permet d'accéder à des bibliothèques partagées natives. Et cela, très simplement, en utilisant les déclarations que l'on trouve dans les fichiers d'inclusion du C.

Par exemple :

local ffi = require 'ffi'
ffi.cdef = [[
int printf(const char *fmt, ...);
]]

ffi.C.printf("Hello %s!", "world")

LuaJIT intègre un parseur C (mais sans le pré-processeur pour les #define, #ifdef).

Ce module permet aussi de manipuler des structures de données natives avec le langage Lua.

Compatibilité avec Lua 5.2

Pendant les 3 ans de développements de LuaJIT2, la version 5.2 du langage Lua a été publiée. En plus d'être totalement compatible avec Lua 5.1, LuaJIT a intégré certaines nouveautés de Lua 5.2. LuaJIT intègre les nouveautés lexicographiques et syntaxiques (l'ajout du goto), ainsi qu'une très grande partie des modifications des bibliothèques standards de Lua. En revanche, le nouveau modèle d'environnement des fonctions (_ENV) est incompatible. De même, l'API C reste celle de Lua 5.1.

Les performances

Le site de LuaJIT présente des comparatifs de performance entre différentes versions de Lua et LuaJIT, pour différentes architectures.

Il y a quelques années, LuaJIT était dans la liste de The Computer Language Benchmarks Game, et les résultats étaient très impressionnants, maintenant il ne reste malheureusement que Lua.

Le modèle de développement

LuaJIT est le fruit du travail d'un seul homme, Mike Pall, qui est un développeur indépendant allemand. Il parvient à se faire rémunérer par certaines sociétés commerciales qui sponsorisent le développement de diverses fonctionnalités.

LuaJIT est diffusé sous la licence MIT, comme Lua.

Les sources sont disponibles dans un dépôt Git (ce qui n'est pas le cas de Lua, où seuls les tarballs sont diffusés).

Depuis mai 2012, LuaJIT a sa propre liste de diffusion, plutôt que d'utiliser celle de Lua.

La suite avec LuaJIT 3.0

Mike Pall nous promet :

  • Un nouveau ramasse-miette (incrémental, générationnel et sans copie) qui devrait être évidemment très performant ;
  • La prise en charge du préprocesseur C et une prise en charge partielle du C++ pour le module FFI.
  • # Pour se faire une idée des perfs

    Posté par (page perso) . Évalué à  10 .

    Le gros avantage de LuaJIT est qu'il ne nécessite aucun travail préparatoire pour remplacer l'interpréteur Lua.
    C'est aussi simple que de remplacer ceci:
    $~ lua foo.lua

    par cela:

    $~ luajit foo.lua

    Et les résultats sont vraiment impressionants. Déja que Lua est plutôt rapide pour un langage interprété, LuaJIT passe vraiment la vitesse supérieure.

    Il est vrai qu'il est dommage que LuaJIT ait été enlevé du «shootout benchmark».

    Néanmoins, pour se faire une idée de ses performances par rapport à Lua, on peut consulter la page dédiée sur le site de Mike Pall. Par exemple, pour les x86 et x86_64:

    http://luajit.org/performance_x86.html

    • [^] # Re: Pour se faire une idée des perfs

      Posté par (page perso) . Évalué à  7 .

      Tiens une news sur luaJIT, surprise du jour

      J'ai toujours trouvé le gain de performance de LuaJIT simplement hallucinant..

      Sur les tests du shootout, LuaJIT avait des perfs qui rivalisait avec "java -server", c'est à ma connaissance le seul langage à typage dynamique/prototype qui peut se permettre ce genre de fantaisie, tous les autres sont loin, trés loin derrière ( d'un facteur 20 environ.. )

      • [^] # Re: Pour se faire une idée des perfs

        Posté par (page perso) . Évalué à  3 .

        y compris PyPy ?

        • [^] # Re: Pour se faire une idée des perfs

          Posté par (page perso) . Évalué à  2 .

          Y compris pypy, je n'ai plus les nombres exactes en tête mais luaJIT mettait un facteur 10 à pypy environ…

          ça doit être possible de se refaire un benchmark maison en fouillant un peu sur le shootaut ;)

          • [^] # Re: Pour se faire une idée des perfs

            Posté par (page perso) . Évalué à  3 .

            Non seulement PyPy, mais aussi toutes les VM JavaScript. En fait sur du calcul scientifique (genre SciMark) LuaJIT est souvent plus rapide que le code C équivalent.

            En plus de ça, la FFI de LuaJIT est vraiment incroyable. La capacité à simplement utiliser n'importe quelle bibliothèque dynamique palie la faible taille de l'écosystème Lua et l'utilisation de ctypes règle souvent les problèmes de mémoire propre aux langages dynamiques.

            Au passage les performances ne viennent pas seulement du JIT. Même en le désactivant, ou sur les plate-formes où il n'est pas disponible, l'interpréteur est plus rapide que l'implémentation de référence PUC Lua d'un facteur 4 environ. Bien sûr ça se paye par une complexité supplémentaire et une portabilité limitée (lire le code de LuaJIT est un bon exercice au passage :p).

            Personnellement ça fait quelques années que Lua est mon langage de prédilection, d'abord pour du scripting dans une application C, mais de plus en plus de manière standalone grâce à LuaJIT.

          • [^] # Re: Pour se faire une idée des perfs

            Posté par (page perso) . Évalué à  2 .

            Facteur 10, facteur 20… Il faudrait peut-être quelques exemples sinon on se retrouve un peu à laver plus blanc que blanc !

          • [^] # Re: Pour se faire une idée des perfs

            Posté par . Évalué à  2 .

            Voila un article qui peut expliquer la différence de perfs entre PyPy et Luajit : http://alexgaynor.net/2011/apr/03/my-experience-computer-language-shootout/

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.