2014-08-31 7 views
5

Mam zadanie intensywne procesora (zapętlając niektóre dane i wyniki oceny). Chcę korzystać z wielu rdzeni, ale moja wydajność jest zdecydowanie gorsza niż użycie pojedynczego rdzenia.nodejs - znajduję wielowątkowość lub używanie wielu procesów jest wolniejsze niż jeden proces. Czemu?

Próbowałem:

  • Tworzenie wielu procesów na różnych portach z express i wysyłanie zadań do tych procesów
  • Korzystanie webworker-threads do uruchamiania zadań w różnych wątków przy użyciu puli wątków

Zmierzam wyniki, licząc całkowitą liczbę powtórzeń, które mogę wykonać i dzieląc przez czas, jaki spędziłem na pracy nad problemem. Podczas korzystania z jednego rdzenia moje wyniki są znacznie lepsze.

niektóre interesujące:

  • mogę określić, kiedy jestem tylko przy użyciu jednego rdzenia i kiedy używam wielu rdzeni poprzez Menedżer zadań. Używam spodziewanej liczby rdzeni.
  • mam dużo pamięci RAM
  • Próbowałem uruchomione na zaledwie 2 lub 3 rdzenie
  • I dodał nextTicks który nie wydaje się wpływać na cokolwiek w tym przypadku
  • Zadania potrwać kilka sekund każdy tak ja nie czuję, że tracę dużo na głowie

Czy masz pojęcie, co się tutaj dzieje?

Aktualizacja dla wątków: Podejrzewam błąd w WebWorker gwinty Pomijanie express do teraz, myślę, że problem może mieć do czynienia z moim pętli nici. Co robię, to tworzenie wątków, a następnie próba ich nieprzerwanego uruchamiania, ale wysyłanie danych między nimi. Mimo że oba wątki zużywają procesor, tylko wątek 0 zwraca wartości. Moje założenie było takie, że generalnie skończyłoby się emitowaniem wiadomości do wątku, który był bezczynny najdłużej, ale nie wydaje się, żeby tak było. Mój zestaw górę wygląda to

ciągu threadtask.js

thread.on('init', function() { 

    thread.emit('ready'); 

    thread.on('start', function(data) { 
     console.log("THREAD " + thread.id + ": execute task"); 
     //... 
     console.log("THREAD " + thread.id + ": emit result"); 
     thread.emit('result', otherData)); 
    }); 
}); 

main.js

var tp = Threads.createPool(NUM_THREADS); 
tp.load(threadtaskjsFilePath); 
var readyCount = 0; 
tp.on('ready', function() { 
    readyCount++; 

    if(readyCount == tp.totalThreads()) { 
     console.log('MAIN: Sending first start event'); 
     tp.all.emit('start', JSON.stringify(data)); 
    } 
}); 

tp.on('result', function(eresult) { 
    var result = JSON.parse(eresult); 
    console.log('MAIN: result from thread ' + result.threadId); 
    //... 
    console.log('MAIN: emit start' + result.threadId); 
    tp.any.emit('start' + result.threadId, data); 
}); 

tp.all.emit("init", JSON.stringify(data2)); 

Wyjście do tej katastrofy

MAIN: Sending first start event 
THREAD 0: execute task 
THREAD 1: execute task 
THREAD 1: emit result 
MAIN: result from thread 1 
THREAD 0: emit result 
THREAD 0: execute task 
THREAD 0: emit result 
MAIN: result from thread 0 
MAIN: result from thread 0 
THREAD 0: execute task 
THREAD 0: emit result 
THREAD 0: execute task 
THREAD 0: emit result 
MAIN: result from thread 0 
MAIN: result from thread 0 
THREAD 0: execute task 
THREAD 0: emit result 
THREAD 0: execute task 
THREAD 0: emit result 
MAIN: result from thread 0 
MAIN: result from thread 0 

próbowałam inne podejście gdzie wyślę wszystkie, ale potem każdy wątek będzie słuchał wiadomości, na którą tylko ona może odpowiedzieć. Np. Thread.on ('start' + thread.id, function() {...}). To nie działa, ponieważ w wyniku, kiedy robię tp.all.emit ("start" + result.threadId, ...), wiadomość nie zostanie odebrana.

MAIN: Sending first start event 
THREAD 0: execute task 
THREAD 1: execute task 
THREAD 1: emit result 
THREAD 0: emit result 

Po tym wszystkim nic więcej się nie dzieje.

Aktualizacja dla wielu serwerów ekspresowych: Dostaję ulepszeń ale mniejszy niż oczekiwano

I revisited tego rozwiązania i miał więcej szczęścia. Myślę, że mój oryginalny pomiar mógł być wadliwy. Nowe wyniki:

  • jednego procesu: 3.3 iteracje/sekundę
  • głównego procesu + 2 serwery: 4.2 iteracje/sekundę
  • głównego procesu + 3 serwery: 4.9 iteracje/sekundę

jedna rzecz Trochę dziwne, że nie widzę około 6 iteracji/sekundę dla 2 serwerów i 9 dla 3. Dostaję, że są pewne straty dla sieci, ale jeśli zwiększę mój czas pracy, aby być wystarczająco wysoki, straty sieci powinny bądźmy drobni, tak bym pomyślał.

+1

Czy jesteś pewien, że jesteś powiązany z procesorem i nie jesteś związany? –

+0

Dość pewne. Czy wiesz, w jaki sposób mogę potwierdzić, że nie jest on związany? Nie ładuję niczego z dysku po zainicjowaniu wątków. Przesyłam kilka tablic jsonów do wątków, ale nie są one ogromne. – i8abug

+0

Miej oko na wykorzystanie dysku/sieci i sprawdź, czy wygląda na wyczerpującą. –

Odpowiedz

1

Nie należy przesuwać procesów Node.js, aby uruchamiać wiele wątków w celu poprawy wydajności. Praca na czterordzeniowym procesorze, z obsługą procesów ogólnych i procesami 1 express i 3 express procesami wymagającymi intensywniejszego procesora, byłaby prawdopodobnie najbardziej efektywną konfiguracją, dlatego sugerowałbym, abyś spróbował zaprojektować swoje procesy express, aby odroczyć korzystanie z Pracownicy sieci i po prostu blokują, dopóki nie osiągną wyniku. Spowoduje to przejście do pojedynczego procesu z jednym wątkiem, zgodnie z projektem, najprawdopodobniej przynosząc najlepsze wyniki.

Nie znam zawiłości synchronizowania pakietu pracowników WWW, wpływa na pule wątków Node.js, które zdarzają się w przestrzeni c itp., Ale wydaje mi się, że ogólnie chcesz wprowadzić pracowników sieciowych aby móc zarządzać większą ilością zadań blokowania w tym samym czasie, bez poważnego wpływu na inne żądania, które nie wymagają wątków ani we/wy systemu, lub w inny sposób można na nie odpowiednio zareagować. Nie musi to oznaczać, że zastosowanie tej metody przyniesie poprawę wydajności dla poszczególnych wykonywanych zadań. Jeśli uruchomisz 4 procesy z 4 wątkami, które wykonują operacje we/wy, możesz zablokować sobie marnowanie czasu na ciągłe przełączanie się między kontekstami wątku poza obszarem aplikacji.

Powiązane problemy