Erlang (langage)

Un article de Wikipédia, l'encyclopédie libre.

Pour les articles homonymes, voir Erlang.

Erlang, (d'après le nom du mathématicien Agner Erlang, mais aussi contraction d'Ericsson Language), est un langage fonctionnel concurrent temps réel et distribué, qui possède des fonctionnalités de tolérance aux pannes, et de mise à jour du code en temps réel pour des applications à haute disponibilité.

Depuis qu'il a été mis sous licence Open Source en 1998, il est utilisé par de nombreuses compagnies de télécommunications pour leurs routeurs téléphoniques, notamment T-Mobile et Nortel. Il est aussi utilisé pour écrire le serveur Jabber ejabberd, ainsi que le logiciel de modélisation 3D Wings 3D. Il possède des interfaces avec d'autres langages comme Java ou C++ et de nombreuses API comme XML ou OpenGL.

Sommaire

[modifier] Exemples

En Erlang, la fonction factorielle s'écrit sous sa forme récursive comme suit :

-module(fact).
-export([fac/1]).

fac(0) -> 1;
fac(N) when N > 0 -> N * fac(N-1).

L'algorithme de tri Quicksort avec une implémentation également récursive s'écrit sous cette forme en Erlang :

%% quicksort:qsort(List)
%% Trie une liste d'éléments
-module(quicksort).
-export([qsort/1]).

qsort([]) -> [];
qsort([Pivot|Reste]) ->
    qsort([ X || X <- Reste, X < Pivot]) ++ [Pivot] ++ qsort([ Y || Y <- Reste, Y >= Pivot]).

Le code fait des appels récursifs à la fonction qsort jusqu'à ce que l'ensemble soit trié. L'expression [ X || X <- Reste, X < Pivot] peut se traduire par « Choisir l'ensemble des X tels que X est un membre de Reste et X est inférieur à Pivot ». L'opérateur ++ est celui de la concaténation entre les listes.

[modifier] Points forts

[modifier] Gestion explicite du temps

Du fait de ses origines comme outil logiciel de télécommunications, Erlang incorpore le temps comme primitive du langage, en utilisant la construction suivante:

receive
    Message1 ->
       Action1;
    Message2 ->
       Action2;
after
    timeout() ->
       ActionTimeOut;
end

Le processus qui exécute le code ci-dessus attendra au plus, la valeur retournée par l'expression timeout(). Si aucun message n'est reçu par le processus d'ici là, il execute alors l'action ActionTimeOut. La précision de la mesure du temps dépend de la plateforme sur laquelle la machine virtuelle Erlang est déployée; les garanties d'exécution ne sont donc pas absolues mais intégrer le temps dans le langage ouvre de fait une dimension complétement nouvelle dans le traitement des erreurs, puisqu'il devient facile de prévoir des traitements spécifiques lorsque des événements attendus par une partie du programme ne se sont pas produits.

[modifier] Le partage de données par passage de message

Contrairement aux langages classiques tels Java ou C, le partage d'information entre processus ne se fait pas conceptuellement par partage de mémoire, mais par passage de message (même si pour des raisons d'efficacité le passage de message peut avoir comme support une zone de mémoire partagée). L'hypothèse de base est donc que différents processus ne partagent aucune donnée, et qu'ils doivent le faire explicitement grâce à une primitive du langage : send, exprimée par !.

Le modèle est le suivant :

Pid ! message

dans lequel Pid est l'identifiant du processus destinataire et message une expression quelconque.

[modifier] La programmation distribuée à base de nœud et de processus

Chaque traitement est effectué par un processus (qui peut être un processus créé et géré par le système d'exploitation ou un procesus géré par la machine virtuelle). Une machine virtuelle qui héberge des processus est aussi appelée nœud. Comme indiqué ci-avant, les processus utilisent les messages pour communiquer entre eux. Un processus peut se trouver sur le même nœud ou sur un autre nœud ; tant que les deux nœuds sont connectés entre eux, le langage utilise la même syntaxe dans l'adressage des processus ou l'envoi de message. C’est-à-dire qu'envoyer un message à un processus sur un autre nœud se fait par les deux actions suivantes, par ordre chronologique :

register(nom_commun_de_mon_processus, Pid)

du côté du destinataire afin que ce dernier soit reconnu dans l'ensemble des nœuds connectés entre eux.

nom_commun_de_mon_processus ! message

du côté de l'envoyeur.

Certains messages inter-processus sont créés automatiquement à l'initiative du nœud lui-même comme le message

{'EXIT', Process_id, Raison}

qui indique que le processus identifié par Process_id vient de se terminer pour la raison Raison. Cela permet à un processus de réagir à la fin, prévue ou non, d'un autre processus.

De la même manière, les nœuds peuvent communiquer entre eux la terminaison de l'un des leurs, afin de pouvoir y réagir. Supposons par exemple qu'une application utilise trois nœuds qui utilisent un service que deux autres nœuds peuvent rendre, donc trois nœuds "clients" et deux nœuds "serveurs". L'un des deux nœuds "serveurs" peut servir toutes les requêtes des trois nœuds "clients" et l'autre nœud "serveur" peut attendre la faillite du premier pour prendre le relais. Puisqu'il est informé de la faillite du premier nœud "serveur" il peut se promouvoir "serveur" principal, et le nœud qui a défailli, pourra, lorsqu'il sera redevenu opérationnel, prendre la place du nœud en attente. Une telle mise en œuvre permet d'obtenir une disponibilité de service sensiblement supérieure à celle que l'on aurait si l'on n'avait qu'un seul nœud "serveur".

[modifier] La richesse de l'environnement

Bâtie sur le langage, les bibliothèques Open Telecom Platform (OTP) offrent des fonctionnalités de distribution des traitements et de supervision des nœuds très avancées, ainsi qu'une base de données répartie. L'accent est très clairement mis sur la tolérance aux pannes puisque le couple Erlang/OTP permet entre autres de :

  • mettre à jour le code d'un programme sans arrêter celui-ci
  • désigner des processus superviseurs qui suivront des instructions bien précises en cas d'arrêt des processus supervisés (redémarrage immédiat ou retardé, décompte du nombre d'erreurs avant de ne plus essayer de redémarrer le processus fautif, etc.)
  • mettre en place une hiérarchie de supervision redondante et centralisée de telle sorte que l'application soit entièrement supervisée tout en répartissant la logique de supervision à chaque niveau.

[modifier] Les points faibles

  • Une documentation bien structurée mais peu abondante, de par le relatif manque de popularité du langage
  • Le traitement de données textuelles assez peu performant

[modifier] Liens externes