Nodes - I find multithreading or several processes slower than a single process. What for?

I have a task with heavy CPU usage (cyclic processing of some data and evaluating the results). I want to use several cores for them, but my performance is consistently worse than just using one core.

I tried:

  • Creation of several processes on different ports with express and sending tasks to these processes
  • Using webworker-threads to run tasks on different threads using a thread pool

I measure the results by counting the total number of iterations I can perform and divide by the amount of time I spent on this problem. When using a single core, my results are much better.

some interesting points:

  • I can determine when I just use one core, and when I use multiple cores through the task manager. I use the expected number of cores.
  • I have a lot of ram
  • I tried to work only on 2 or 3 kernels.
  • I added nextTicks, which does not seem to affect anything in this case
  • Tasks take a few seconds, so I don't feel like losing a lot of overhead

Any idea what is going on here?

Update for threads: I suspect an error in webworker-threads Skipping express at the moment, I think the problem may be related to my thread loop. What I'm doing is creating threads, and then trying to constantly run them, but send data back and forth between them. Although both threads use a processor, only thread 0 returns values. My assumption was that any one of them, as a rule, ultimately emitted a message into a stream that was idle for longer, but this does not seem to be the case. My setup looks like this:

Inside 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)); 

Result of this disaster

 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 

I tried another approach, where I would choose everything, but then each thread listened to a message to which it could respond. For example, thread.on ('start' + thread.id, function () {...}). This does not work, because as a result, when I do tp.all.emit ('start' + result.threadId, ...), the message does not receive.

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

After that, nothing happens.

Update for multiple express servers: I get improvements, but less than expected

I reviewed this decision and had more luck. I think my initial measurement may have been erroneous. New Results:

  • Single process: 3.3 iterations / sec
  • Main process + 2 servers: 4.2 iterations / sec
  • The main process + 3 servers: 4.9 iterations / sec

One thing that I find a little strange is that I do not see about 6 iterations per second for 2 servers and 9 for 3. I understand that there are some losses for working on the network, but if I increase the time of my task, to be high enough, network losses should be pretty small, I would think.

+5
source share
1 answer

You cannot run your Node.js processes to run multiple threads to improve performance. Working on a quad-core processor with 1 express processing common requests and 3 express processes processing intensive CPU requests is likely to be the most efficient installation, so I would suggest you try creating your express postpone the use of web workers and just block until they will not lead to a result. This will lead you to start a single process with a single thread in accordance with the design, which is likely to give the best results.

I donโ€™t know the intricacies of how the web worker package handles synchronization, affects the Node.js I / O pools that occur in space c , etc., but I think that you would usually like to implement the web -workers, in order to be able to simultaneously manage large locking tasks, without seriously affecting other requests that do not require streaming and system I / O, or otherwise it may be advisable to respond. This does not necessarily mean that applying this will increase productivity for specific tasks. If you start 4 processes with 4 threads that perform I / O, you can block yourself by spending time continuously switching between thread contexts outside the application space.

+1
source

Source: https://habr.com/ru/post/1201510/


All Articles