2015-06-07 8 views
6

Szukałem, jak mogę osadzić języki (użyjmy Lua jako przykładu) w Erlang. To oczywiście nie jest nowy pomysł i istnieje wiele bibliotek, które mogą to zrobić. Zastanawiałem się jednak, czy można uruchomić Genserver ze stanem zmodyfikowanym przez Lua. Oznacza to, że po uruchomieniu Genserver rozpocznie się (długotrwały) proces Lua, aby manipulować stanem Genserver. Wiem, że to również możliwe, ale zastanawiałem się, czy mogę odrodzić 1000 10 000, a nawet 100 000 tych procesów.Erlang spawning duże ilości procesów C

Nie znam tego tematu, ale zrobiłem pewne badania. (Proszę poprawić mnie, jeśli się mylę przy którejkolwiek z tych opcji).

TLDR; Przejdź do ostatniego akapitu.

pierwsza opcja: NFI:

To nie wydaje się opcja, ponieważ będzie blokować Erlang Scheduler aktualnego procesu. Jeśli chcę odrodzić dużą ich ilość, zamrozi cały czas działania.

Druga opcja: Port Kierowca:

To jak NIF ale komunikuje się poprzez wysłanie danych do określonego portu, który może również wysyłać dane z powrotem do Erlang. To jest miłe, chociaż wydaje się, że blokuje to harmonogram. Wypróbowałem bibliotekę, która obsługuje również kotłów, ale zdawało się, że blokuje harmonogram po utworzeniu 10 procesów. Zajrzałem również do postgresql przykład na Dokumentacji Erlang, która jest podobno asynchroniczne, ale nie mogłem uzyskać przykładowy kod do pracy (R13?). Czy możliwe jest uruchamianie wielu procesów sterownika portu bez blokowania środowiska wykonawczego?

Trzecia opcja: C Węzły:

Myślałem, że to bardzo ciekawy i chciałem go wypróbować, ale widocznie projekt „Erlang-lua” już to robi. To miło, ponieważ nie zawiedzie twojej maszyny Erlang VM, jeśli coś pójdzie nie tak i procesy zostaną odizolowane. Aby jednak odrodzić się w jednym procesie, trzeba odrodzić cały węzeł. Nie mam pojęcia, ile to kosztuje. Nie jestem też pewny, jaki jest limit łączenia węzłów w klastrze, ale nie widzę siebie odradzania 100 000 węzłów C.

Czwarta opcja: Porty:

Na początku myślałem, że to było takie samo jak sterownik portu, ale to faktycznie inna. Odradzasz proces, który wykonuje aplikację i komunikuje się przez STDIN i STDOUT. Byłoby to dobre rozwiązanie do tworzenia wielu procesów i (jak sądzę?), Że nie stanowią one zagrożenia dla maszyny wirtualnej Erlang. Ale jeśli mam zamiar komunikować się za pomocą STDIN/STDOUT, to po co zawracać sobie głowę językiem z możliwością osadzania? Równie dobrze można użyć dowolnego innego języka skryptowego.

Po wielu badaniach na polu, z którym nie jestem zaznajomiony, doszedłem do tego. Możesz Genserver jako "byt", gdzie AI jest napisane w Lua. Właśnie dlatego chciałbym mieć procesy dla każdej jednostki. Moje pytanie brzmi: w jaki sposób mogę stworzyć wiele genserverów, które komunikują się z długimi procesami Lua? Czy to możliwe? Czy powinienem inaczej radzić sobie z moim problemem?

+0

Czy kod Lua naprawdę musi całkowicie przejąć wątek jądra? Czy może być skonfigurowany w taki sposób, aby mógł zarejestrować się w wywołaniu zwrotnym lub powiadomieniu, aby mógł ponownie podać wątek jądra do Erlanga, a następnie oddzwonić, gdy wydarzenie, które go interesuje, nastąpi? –

+0

W konkretnym przypadku Lua możesz zajrzeć na https://github.com/rvirding/luerl, który jest implementacją Lua w Erlang. Wystarczy załadować i uruchomić kod Lua w procesie erlang (dzięki czemu można mieć wiele równoczesnych oceniających Lua). – johlo

Odpowiedz

3

Jeśli możesz wprowadzić kod Lua — lub dokładniej, jego podstawowy kod macierzysty — współpracuje z maszyną Erlang VM, masz kilka możliwości.

Rozważ jedną z najważniejszych funkcji maszyny Erlang VM: zarządzanie wykonaniem (potencjalnie dużej liczby) lekkich procesów Erlanga w stosunkowo małym zestawie wątków programu planującego. Korzysta z kilku technik, aby wiedzieć, kiedy proces wykorzystał timelice lub czeka, dlatego należy zaplanować, aby inny proces mógł zostać uruchomiony.

Wygląda na to, że pytasz, jak możesz uruchomić kod natywny, ale w VM, ale jak już zauważyłeś, powodem, dla którego kod natywny może powodować problemy dla maszyny wirtualnej, jest brak praktycznego sposobu powstrzymaj cały kod natywny przed całkowitym przejęciem wątku programu planującego, uniemożliwiając w ten sposób wykonywanie regularnych procesów Erlanga. Z tego powodu kod natywny musi wspólnie dostarczać wątek programu planującego z powrotem do maszyny wirtualnej.

Dla starszych NFI, wybory dotyczące tej współpracy były:

  1. Przechowywać czas połączenia NIF biegł na nitce scheduler do 1 ms lub mniej.
  2. Utwórz jeden lub więcej prywatnych wątków. Przejście każdego długo działającego połączenia NIF z wątku programu planującego do wątku prywatnego w celu wykonania, a następnie zwrócenie wątku programu planującego do maszyny wirtualnej.

Problem polega na tym, że nie wszystkie połączenia mogą zostać zakończone w ciągu 1ms lub mniej i że zarządzanie prywatnymi wątkami może być podatne na błędy. Aby obejść pierwszy problem, niektórzy programiści podzielili pracę na porcje i użyli funkcji Erlang jako opakowania do zarządzania serią krótkich połączeń NIF, z których każdy zakończył jedną porcję pracy. Co do drugiego problemu, cóż, czasami po prostu nie można tego uniknąć, pomimo jego nieodłącznych trudności.

NIF-y działające w wersji Erlang 17.3 lub nowszej mogą również wspólnie produkować wątek harmonogramu przy użyciu enif_schedule_nif function. Aby skorzystać z tej funkcji, natywny kod musi być w stanie wykonać swoją pracę w porcjach, tak aby każdy fragment mógł się zakończyć w zwykłym oknie wykonawczym NIF 1ms, podobnie do wspomnianego wcześniej podejścia, ale bez konieczności sztucznego powrotu do opakowania Erlanga. Mój bitwise example code dostarcza wiele szczegółów na ten temat.

Erlang 17 przyniósł domyślnie funkcję eksperymentalną o nazwie dirty schedulers. Jest to zestaw programistów VM, które nie mają tego samego ograniczenia czasu wykonywania kodu natywnego co regularne harmonogramy; praca może tam blokować w zasadzie nieskończone okresy bez zakłócania normalnej pracy maszyny wirtualnej.

Dirty schedulery występują w dwóch wersjach: harmonogramy procesora CPU dla pracy procesora i harmonogramy we/wy dla operacji związanych z I/O. W maszynie wirtualnej skompilowanej do włączania zabrudzonych programów szeregujących domyślnie jest tyle nieczytelnych programów planujących procesorów, ile jest regularnych programów planujących, a ponadto istnieje 10 programów planujących wejścia/wyjścia. Liczby te można zmieniać za pomocą przełączników wiersza polecenia, ale należy pamiętać, że aby zapobiec regularnemu głodzeniu harmonogramu, nigdy nie można mieć bardziej brudnych harmonogramów procesora niż regularne harmonogramy. Aplikacje używają tej samej wymienionej wcześniej funkcji enif_schedule_nif do wykonywania NIF-ów w zabrudzonych programach szeregujących. Mój bitwise example code dostarcza również wiele szczegółów na ten temat. Dirty schedulery pozostaną eksperymentalną funkcją także dla Erlanga 18.

natywnego kodu w linkowane w kierowców portowych podlega tym samym ograniczeniom czasu na wykonanie-scheduler jak NFI, ale kierowcy mają dwie funkcje NFI nie:

  1. Kod kierowcy mogą zarejestrować deskryptorów plików do Podsłuchy VM i otrzymają powiadomienie, gdy któryś z tych deskryptorów plików stanie się gotowy do pracy we/wy.
  2. Interfejs API sterownika obsługuje dostęp do asynchronicznej puli wątków innej niż planista, której rozmiar można konfigurować, ale domyślnie ma 10 wątków.

Pierwsza funkcja pozwala natywnemu kodowi sterownika uniknąć blokowania wątku dla operacji we/wy. Na przykład, zamiast wykonywania połączenia blokującego recv, kod sterownika może zarejestrować deskryptor pliku gniazda, aby maszyna wirtualna mogła go odpytać i przywrócić sterownik, gdy deskryptor pliku stanie się czytelny.

Drugi element zapewnia oddzielną pulę wątków przydatną do zadań sterowników, które nie są w stanie dostosować się do ograniczeń czasu wykonywania natywnego kodu dla harmonogramu. Możesz osiągnąć to samo w NIF, ale musisz skonfigurować własną pulę wątków i napisać swój własny kod natywny, aby zarządzać i uzyskiwać do niego dostęp. Ale niezależnie od tego, czy korzystasz z asynchronicznej puli wątków sterownika, własnej puli wątków NIF, czy brudnych harmonogramów, pamiętaj, że wszystkie są zwykłymi wątkami systemu operacyjnego, a więc próba uruchomienia ich ogromnej liczby po prostu nie jest praktyczna.

Rodzimy kod sterownika nie ma jeszcze brudnego dostępu do programu planującego, ale ta praca jest w toku i może stać się dostępna jako funkcja eksperymentalna w wydaniu 18.x.

Jeśli twój kod Lua może korzystać z jednej lub więcej z tych funkcji do współpracy z maszyną Erlang VM, możesz podjąć próbę.

+0

Dziękuję za dokładne wyjaśnienie. Bardzo mi to wyjaśniło. Będę badać te opcje i zobaczę, czy uda mi się znaleźć rozwiązanie. Dzięki jeszcze raz! – Attic

Powiązane problemy