79 votes

Le modèle d'acteur: Pourquoi erlang special? Ou, pourquoi avez-vous besoin d'une autre langue pour cela?

J'ai été à la recherche dans l'apprentissage de la erlang, et, en conséquence, avoir lu (bon d'accord, l'écrémage) sur le modèle de l'acteur.

Ce que je comprends, l'acteur modèle est tout simplement un ensemble de fonctions (exécuter dans un délai de légers fils appelé "processus" en erlang), qui communiquent les uns avec les autres via la transmission de message.

Cela semble assez facile à implémenter en C++, ou en toute autre langue:

class BaseActor {
    std::queue<BaseMessage*> messages;
    CriticalSection messagecs;
    BaseMessage* Pop();
public:
    void Push(BaseMessage* message)
    {
        auto scopedlock = messagecs.AquireScopedLock();
        messagecs.push(message);
    }
    virtual void ActorFn() = 0;
    virtual ~BaseActor() {} = 0;
}

Avec chacun de vos processus en cours d'une instance d'un dérivé BaseActor. Les acteurs de communiquer les uns avec les autres seulement par passage de message. (à savoir, pousser). Les acteurs s'inscrire eux-mêmes au centre de la carte lors de l'initialisation qui permet à d'autres acteurs pour les trouver, et permet une fonction centrale à courir à travers eux.

Maintenant, je comprends que je suis absent, ou plutôt, dissimuler une question importante, à savoir: manque de rendement moyen d'un seul Acteur peut injustement consommer trop de temps. Mais la croix-plate-forme de coroutines la principale chose qui rend cette dur en C++? (Windows, par exemple, a des fibres.)

Est-il autre chose que je suis absent, mais, ou est le modèle vraiment ce évident?

Je ne suis certainement pas en essayant de démarrer une flamme de guerre ici, je veux juste comprendre ce que je suis absent, comme c'est essentiellement ce que j'ai déjà faites pour être en mesure à un peu raison sur code simultané.

87voto

Lukas Points 3782

Le code C++ ne permet pas de traiter avec équité, l'isolement, la détection de défaut ou de distribution, qui sont toutes des choses qui Erlang apporte dans le cadre de son acteur modèle.

  • Pas d'acteur est autorisé à mourir de faim tout autre acteur (l'équité)
  • Si un acteur se bloque, elle ne devrait toucher que l'acteur (l'isolement)
  • Si un acteur se bloque, d'autres acteurs doivent être capables de détecter et de réagir à l'accident (détection de défaut)
  • Les acteurs doivent être en mesure de communiquer sur un réseau comme s'ils étaient sur la même machine (distribution)

Aussi le faisceau SMP émulateur apporte JIT de planification des acteurs, en les déplaçant vers le noyau qui est à l'heure actuelle l'un avec moins d'utilisation et aussi hiberne les fils sur certains cœurs si elles ne sont plus nécessaires.

En outre, tous les outils et de bibliothèques écrit en Erlang peut supposer que c'est la façon dont le monde fonctionne et être conçus en conséquence.

Ces choses ne sont pas impossible de le faire en C++, mais ils deviennent de plus en plus difficile, si vous ajoutez le fait que Erlang fonctionne sur presque tous les grands hw et os configurations.

edit: Viens de trouver une description par Ulf Wiger à propos de ce qu'il voit erlang style de la simultanéité comme.

32voto

rvirding Points 13019

Je n'aime pas me citer, mais à partir de virding a la Première Règle de la Programmation

Tout suffisamment compliqué programme concurrent dans une autre langue contient un groupe ad hoc de manière informelle-spécifiés de bogue en proie à la lenteur de mise en œuvre de la moitié d'Erlang.

À l'égard de Greenspun. Joe (Armstrong) a une règle similaire.

Le problème n'est pas de mettre en œuvre les acteurs, ce n'est pas que difficile. Le problème est de mettre tout travailler ensemble: les processus, la communication, la collecte des ordures, des langues primitives, erreur de manipulation, etc ... Par exemple à l'aide de threads OS échelles de mal si vous avez besoin de le faire vous-même. Ce serait comme essayer de "vendre" un langage OO où vous ne pouvez avoir 1k objets et ils sont lourds à créer et à utiliser. De notre point de vue, la simultanéité est la base de l'abstraction de la structuration des applications.

Se laisser emporter donc je vais m'arrêter ici.

22voto

jaten Points 136

C'est en fait une excellente question, et a reçu d'excellentes réponses qui sont peut-être encore plus convaincant.

Pour ajouter de l'ombre et de l'accent à l'autre de grandes réponses déjà ici, pensez à ce que Erlang prend à l'écart (par rapport aux traditionnelles à des fins générales de langages tels que C/C++) pour atteindre la tolérance de panne et la disponibilité.

D'abord, il enlève les verrous. Joe Armstrong livre expose cette expérience de pensée: supposons que votre processus de acquiert un verrou, puis se bloque immédiatement (un mémoire de problème, entraîne le processus de l'accident, ou le pouvoir ne parvient pas à une partie du système). La prochaine fois qu'un processus attend que même de verrouillage, le système vient de l'impasse. Cela pourrait être une raison évidente de verrouillage, comme dans le AquireScopedLock() dans l'exemple de code; ou il pourrait être implicite verrou acquis sur votre compte par un gestionnaire de mémoire, dire lors de l'appel de malloc() ou free().

Dans tous les cas, votre processus de crash a désormais stoppé l'ensemble du système de progresser. Fini. Fin de l'histoire. Votre système est mort. Sauf si vous pouvez garantir que chaque bibliothèque que vous utilisez dans le C/C++ n'appelle jamais malloc et jamais acquiert un verrou, votre système n'est pas tolérant aux pannes. Erlang systèmes peuvent tuer les processus à volonté sous une lourde charge dans le but de faire des progrès, donc, à l'échelle de votre processus Erlang doit être tuables (à tout point unique de l'exécution) afin de maintenir le débit.

Il y a une solution partielle: à l'aide de contrats de location partout à la place de serrures, mais vous n'avez aucune garantie que toutes les bibliothèques que vous utilisez aussi le faire. Et la logique et le raisonnement à propos de l'exactitude devient vraiment poilue rapidement. En outre, de location de récupérer lentement (après l'expiration de ce délai), de sorte que l'ensemble de votre système d'suis vraiment lent face à l'échec.

Deuxièmement, Erlang enlève le typage statique, qui permet à son tour de hot code swapping et l'exécution de deux versions du même code simultanément. Cela signifie que vous pouvez mettre à jour votre code à l'exécution sans arrêter le système. C'est la façon dont les systèmes rester en place pendant neuf 9 ou 32 ms de temps d'arrêt/an. Ils sont tout simplement mis à jour. Vos fonctions C++ devra être manuellement re-lié pour être mis à niveau, et l'exécution de deux versions en même temps n'est pas pris en charge. Code de mises à jour nécessitent d'indisponibilité du système, et si vous avez un grand groupe qui ne peut pas exécuter plus d'une version de code à la fois, vous aurez besoin de prendre l'ensemble du cluster vers le bas à la fois. Ouch. Et dans le secteur des télécommunications monde, n'est pas tolérable.

En outre Erlang enlève la mémoire partagée et partagé partagé la collecte des ordures, chaque poids léger processus de garbage collecté de façon indépendante. C'est une simple extension du premier point, mais insiste sur le fait que pour la vraie tolérance de panne vous avez besoin de processus qui ne sont pas enclenchées en termes de dépendances. Cela signifie que votre GC pauses par rapport à java sont tolérables (petites au lieu de la suspension d'une demi-heure pour un 8GO GC) pour les grands systèmes.

14voto

Alexey Romanov Points 39124

Il existe des bibliothèques d’acteurs pour C ++:

Et une liste de certaines bibliothèques pour d'autres langues.

2voto

Matthias Vallentin Points 4165

Casablanca est un autre nouveau venu dans le bloc modèle des acteurs. Une acceptation asynchrone typique ressemble à ceci:

 PID replyTo;
NameQuery request;
accept_request().then([=](std::tuple<NameQuery,PID> request)
{
   if (std::get<0>(request) == FirstName)
       std::get<1>(request).send("Niklas");
   else
       std::get<1>(request).send("Gustafsson");
}
 

(Personnellement, je trouve que libcppa cache mieux le motif correspondant derrière une belle interface.)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X