Przez ostatni tydzień pracowałem nad wielowątkową implementacją środowiska wykonawczego JavaScript. Mam dowód koncepcji wykonany w C ++ przy użyciu JavaScriptCore i boost.
Architektura jest prosta: gdy środowisko wykonawcze zakończy ocenę skryptu głównego, uruchamia się i dołącza do puli wątków, która rozpoczyna pobieranie zadań ze wspólnej kolejki priorytetowej, jeśli dwa zadania próbują jednocześnie uzyskać dostęp do zmiennej, zostaje oznaczona jako atomowa i walczą o dostęp .
Problem polega na tym, że kiedy pokazuję ten projekt programistom JavaScript, otrzymuję bardzo negatywne opinie i nie mam pojęcia, dlaczego. Nawet prywatnie wszyscy mówią, że JavaScript ma być jednowątkowy, że istniejące biblioteki będą musiały zostać przepisane, a gremliny odrodzą się i zjadają każdą żywą istotę, jeśli będę dalej nad tym pracował.
Początkowo miałem też natywną implementację coroutine (wykorzystującą konteksty doładowania), ale musiałem to porzucić (JavaScriptCore ma pedantyczny stosunek do stosu), i nie chciałem ryzykować ich gniewu, więc postanowiłem o tym nie wspominać.
Co myślisz? Czy JavaScript ma być jednowątkowy i czy należy go zostawić w spokoju? Dlaczego wszyscy są przeciwni idei jednoczesnego uruchamiania środowiska JavaScript?
Edycja: Projekt jest teraz na GitHub , eksperymentuj z nim sam i daj mi znać, co myślisz.
Poniżej znajduje się obraz obietnic działających na wszystkich rdzeniach procesora równolegle bez rywalizacji:
źródło
Odpowiedzi:
1) Wielowątkowość jest niezwykle trudna i niestety sposób, w jaki przedstawiłeś ten pomysł do tej pory, oznacza, że poważnie nie doceniasz jej trudności.
W tej chwili wygląda na to, że po prostu „dodajesz wątki” do języka i martwisz się, jak poprawić go i poprawić. W szczególności:
Dodanie wątków do Javascript bez „rozwiązania problemu synchronizacji” byłoby jak dodanie liczb całkowitych do Javascript bez „rozwiązania problemu dodawania”. Jest to tak fundamentalne dla natury problemu, że w zasadzie nie ma nawet sensu dyskutować, czy wielowątkowość warto dodać bez konkretnego rozwiązania, bez względu na to, jak bardzo byśmy tego chcieli.
Co więcej, przekształcanie atomów w wszystkie zmienne to coś, co może sprawić, że program wielowątkowy będzie działał gorzej niż jego jednorzędowy odpowiednik, co sprawia, że jeszcze ważniejsze jest testowanie wydajności w bardziej realistycznych programach i sprawdzanie, czy coś zyskujesz, czy nie.
Nie jest też dla mnie jasne, czy próbujesz ukryć wątki przed programistą node.js, czy planujesz je w pewnym momencie ujawnić, tworząc nowy dialekt JavaScript dla programowania wielowątkowego. Obie opcje są potencjalnie interesujące, ale wygląda na to, że jeszcze nie zdecydowałeś, na którą celujesz.
W tej chwili prosi się programistów o rozważenie przejścia ze środowiska jedno-wątkowego na zupełnie nowe środowisko wielowątkowe, w którym nie ma rozwiązania problemu z synchronizacją i nie ma dowodów na to, że poprawia ono wydajność w świecie rzeczywistym, i pozornie nie ma planu rozwiązania tych problemów.
Prawdopodobnie dlatego ludzie nie traktują cię poważnie.
2) Prostota i niezawodność pętli pojedynczych zdarzeń jest ogromną zaletą.
Programiści Javascript wiedzą, że język JavaScript jest „bezpieczny” przed warunkami wyścigowymi i innymi wyjątkowo podstępnymi błędami, które nękają wszystkie autentycznie wielowątkowe programy. Fakt, że potrzebują silnych argumentów, aby przekonać ich do rezygnacji z bezpieczeństwa, nie czyni ich zamkniętymi, lecz czyni z nich odpowiedzialnymi.
O ile nie uda ci się w jakiś sposób zachować tego bezpieczeństwa, każdemu, kto zechce przełączyć się na wielowątkowy node.js, prawdopodobnie lepiej będzie przejść na język taki jak Go, zaprojektowany od podstaw dla aplikacji wielowątkowych.
3) JavaScript obsługuje już „wątki w tle” (WebWorkers) i programowanie asynchroniczne bez bezpośredniego udostępniania zarządzania wątkami programiście.
Te funkcje rozwiązują już wiele typowych przypadków użycia, które wpływają na programistów Javascript w prawdziwym świecie, bez rezygnacji z bezpieczeństwa pętli pojedynczych zdarzeń.
Czy masz na myśli jakieś szczególne przypadki użycia, których nie rozwiązują te funkcje i dla których programiści Javascript chcą rozwiązania? Jeśli tak, dobrym pomysłem byłoby zaprezentowanie swojego wielowątkowego node.js w kontekście tego konkretnego przypadku użycia.
PS Co przekonałoby mnie do przejścia na wielowątkową implementację node.js?
Napisz nietrywialny program w Javascript / node.js, który Twoim zdaniem mógłby skorzystać z autentycznej wielowątkowości. Wykonaj testy wydajności tego przykładowego programu w normalnym węźle i węźle wielowątkowym. Pokaż, że Twoja wersja w znacznym stopniu poprawia wydajność, czas reakcji i użycie wielu rdzeni, bez żadnych błędów i niestabilności.
Kiedy to zrobisz, myślę, że zobaczysz ludzi o wiele bardziej zainteresowanych tym pomysłem.
źródło
Zgaduję tutaj, aby zademonstrować problem w twoim podejściu. Nie mogę przetestować tego pod kątem rzeczywistej implementacji, ponieważ nigdzie nie ma linku ...
Powiedziałbym, że dzieje się tak, ponieważ niezmienniki nie zawsze są wyrażane przez wartość jednej zmiennej, a „jedna zmienna” nie wystarcza, aby być zakresem blokady w ogólnym przypadku. Wyobraźmy sobie na przykład, że mamy niezmiennik
a+b = 0
(saldo banku z dwoma kontami). Dwie poniższe funkcje zapewniają, że niezmiennik jest zawsze przechowywany na końcu każdej funkcji (jednostka wykonania w jednowątkowym JS).Teraz w wielowątkowym świecie, co się dzieje, gdy dwa wątki wykonania
withdraw
ideposit
w tym samym czasie? Dzięki, Murphy ...(Być może masz kod, który traktuje + = i - = specjalnie, ale to nie pomaga. W pewnym momencie będziesz mieć stan lokalny w funkcji i bez możliwości zablokowania dwóch zmiennych w tym samym czasie niezmiennik zostać naruszonym.)
EDYCJA: Jeśli twój kod jest semantycznie równoważny kodowi Go na https://gist.github.com/thriqon/f94c10a45b7e0bf656781b0f4a07292a , mój komentarz jest poprawny ;-)
źródło
Dziesięć lat temu Brendan Eich (wynalazca JavaScript) napisał esej zatytułowany „ Threads Suck” , który jest zdecydowanie jednym z niewielu kanonicznych dokumentów dotyczących mitologii projektowania JavaScript.
Czy to prawda, to kolejne pytanie, ale myślę, że miało to duży wpływ na to, jak społeczność JavaScript myśli o współbieżności.
źródło
Dostęp atomowy nie przekłada się na zachowanie bezpieczne dla wątków.
Jednym z przykładów jest sytuacja, w której globalna struktura danych musi być niepoprawna podczas aktualizacji, takiej jak zmiana skrótu (na przykład podczas dodawania właściwości do obiektu) lub sortowanie tablicy globalnej. W tym czasie nie można zezwolić na dostęp do zmiennej przez inny wątek. Zasadniczo oznacza to, że musisz wykryć całe cykle odczytu-aktualizacji-zapisu i zablokować to. Jeśli aktualizacja nie jest trywialna, spowoduje to zatrzymanie problematycznego terytorium.
JavaScript jest od początku jednowątkowy i piaskowiony, a cały kod jest napisany z uwzględnieniem tych założeń.
Ma to wielką zaletę w odniesieniu do izolowanych kontekstów i pozwala na uruchamianie 2 oddzielnych kontekstów w różnych wątkach. Mam również na myśli, że ludzie piszący javascript nie muszą wiedzieć, jak radzić sobie z warunkami wyścigu i różnymi innymi wielowątkowymi błędami.
źródło
Czy Twoje podejście znacząco poprawi wydajność?
Wątpliwy. Naprawdę musisz to udowodnić.
Czy Twoje podejście ułatwi / przyspieszy pisanie kodu?
Zdecydowanie nie, kod wielowątkowy jest wielokrotnie trudniejszy do uzyskania niż kod jednowątkowy.
Czy twoje podejście będzie bardziej niezawodne?
Zakleszczenia, warunki wyścigu itp. To koszmar do naprawienia.
źródło
Twoja implementacja nie polega tylko na wprowadzeniu współbieżności, ale raczej na wprowadzeniu określonego sposobu implementacji współbieżności, tj. Współbieżności według współdzielonego stanu zmiennego. W ciągu historii ludzie korzystali z tego rodzaju współbieżności, co doprowadziło do wielu problemów. Oczywiście możesz tworzyć proste programy, które doskonale współpracują ze współdzieloną zmienną współbieżnością stanu, ale prawdziwy test dowolnego mechanizmu nie jest tym, co potrafi, ale można go skalować, gdy program się komplikuje, a do programu dodaje się coraz więcej funkcji. Pamiętaj, że oprogramowanie nie jest statyczną rzeczą, którą budujesz raz i po zakończeniu, a raczej ewoluuje w czasie i jeśli jakikolwiek mechanizm lub koncepcja może ”
Możesz spojrzeć na inne modele współbieżności (np. Przekazywanie wiadomości), aby dowiedzieć się, jakie korzyści zapewniają te modele.
źródło
To jest potrzebne. Brak mechanizmu niskiego poziomu współbieżności w węźle js ogranicza jego zastosowania w takich dziedzinach, jak matematyka i bioinformatyka itp. Poza tym współbieżność z wątkami niekoniecznie koliduje z domyślnym modelem zgodności stosowanym w węźle. Istnieją dobrze znane semantyki dotyczące wątków w środowisku z główną pętlą zdarzeń, takich jak frameworki interfejsu użytkownika (i nodejs), i które są zdecydowanie zbyt skomplikowane w większości sytuacji, w których nadal mają prawidłowe zastosowania.
Jasne, twoja przeciętna aplikacja internetowa nie będzie wymagała wątków, ale spróbuj zrobić coś nieco mniej konwencjonalnego, a brak prymitywnej współzależności niskiego poziomu szybko porwie cię do czegoś innego, co ją oferuje.
źródło
Naprawdę wierzę, że to dlatego, że jest to inny i potężny pomysł. Przeciwstawiasz się systemom przekonań. Rzeczy stają się akceptowane lub popularne przez wpływy sieciowe nie na podstawie zasług. Również nikt nie chce przystosować się do nowego stosu. Ludzie automatycznie odrzucają rzeczy, które są zbyt różne.
Jeśli możesz wymyślić sposób, aby przekształcić go w zwykły moduł npm, który wydaje się mało prawdopodobny, być może niektórzy z niego skorzystają.
źródło