I regularly hear a phrase like “Node.js is not suitable for high-speed content”.
I wanted to see for myself.
I wanted to write a comment on
that article, but changed my mind and wrote more. The author of that article, thank you very much for the interesting topic, hurt.
')
On the Internet, someone is wrong. Our beat! It's a shame, yes. I made some conclusions for myself, but these are my subjective numbers. What to think in general - I do not know, please write your opinion in kamentah.
UPD 3 According to the results of the discussion, what I needed to write from the very beginning was found, what I meant, namely: that the test is not representative, the only thing that it shows is that On My very weak machine, the node lags on Nginx half an order . Noda, like Nginx, does almost nothing, in this sense they are “equal”. I wanted to show that there is a taskset, that a node can not overload a percent under certain conditions, that it is not necessary to believe the tests.
Link to GIT under the cut is. There are some configs that are optimal only for me. The article is confused and for the most part comic. Please - do not read if you are not ready to be suspicious of numbers, benchmarks and strange conclusions of people unfamiliar to you, expressing their thoughts with the constantly changing context of associative references to the humanitarian thinking.
UPD 1 a little bit like “humor”, m. B. so it will be more correct.
UPD 2 Do not believe a single word!
I am a shaman! I quietly take a tambourine in my hands and uncover the
harp ...
I do not like resources, because I understand that in case of emergency I will not have them.
Therefore, I have them very modest:
AMD C-60 /4 Gb / SSD.
All this is packed in a netbook, weighs about a kilogram and is managed by Linux Mint. I anticipate questions, so I will answer immediately. Yes, it also happens that I cook. I also know how to embroider with a cross like
Matroskin .
I sing the guitar like
Elvis . At home there I can hammer a nail with pliers. In general - a gift to the family: an indispensable specialist of a wide profile.
And I enjoy programming in JavaScript. No, I can read Python, Ruby, PHP, Perl, VB, C #, Java, etc. But I can not write, "the soul does not lie." And I have no education, IT-shnoy, so I use banal logic and the fact that by nature I sometimes prefer to think with my own head, and not with someone else's. And so I live.
Customers have set me the task of spherical comparative analysis of Node.JS and Nginx. Since it was necessary to measure the potential performance of the node itself, then the task was set slyly:
- NGINX gives only its default static index.html page.
- The Node server must count the connections and give the result in each response, as well as the maximum number.
- Client software should count the number of processed requests per second, i.e. successfully completed with status 200 OK.
It is clear that nginx will win. But the essence is not in it, but in comparison. Those. exactly how many times the node interpreter is worse than the static Nginx.
Of course, I understand that it is also possible to force a node to render static. But you try to teach nginx business logic in a dozen tables in a couple of hours?
The link to git will be at the end. Use Case for those who are "in the tank" will be there.
I'll tell you a little how I came to this, to, so to speak, dispel doubts.
We all know that modern processors work consistently.
We know everything, but we understand what we want, and not as it is right!
Tell me, can you think of several things at once? And if at this moment the phone rings and you need to answer the call? And if, in parallel with the phone, a person-colleague approaches you, to whom [oh || mu] do you have sympathy and ask some very important question? And if, at the same time, a BOSS man passes by suddenly, looks at the screen on which Lurk flaunts in an undisturbed browser window or something else?
This is the same - interrupt handling and stack overflow.
It would seem - what does asynchrony?
But, if you, all of a sudden, for some terrible reason still did not fully understand, I advise you to think again.
For example, your brain can hold 8 operational tasks, for example, by analogy with 8 cores of the core. The rest - they are somewhere there, sometime they will be, they are still far away.
Think how you can imagine it, play
Estinstein Chtol. It turns out you have all the multithreading there only in your head to hold (as in L1-L2 Cache), meaning, yes - without the leaf (Mem)?
Now let's count.
You run your attachment on the node, you have a standard code there, maybe
from here .
var cluster = require('cluster'); var numCPUs = require('os').cpus().length; ... for (var i = 0; i < numCPUs; i++) { cluster.fork(); ...
Or something similar, with multithreading.
What do you think, who will drive the flows?
That's right - Operating System.
And in the system who drives them?
That's right - Linux Kernel \ Windows Core - Hardware Abstraction Layer (hal.dll, I guess I could be wrong).
So far, it seems, there is nothing suspicious.
But let's still think a little more!
Suppose, besides the node, nothing else is established at all.
What else is on this "hardware" besides her?
That's right - Operating System.
And in it all the tripe that steers the flow. Doesn't it seem mysterious to you that such a simple thing as consecutive instructions, even in asynchronous mode, is serviced and abstracted by such a complex thing as multithreading and parallelism of tasks in the kernel world?
So, each of the iron cores of the processor counts sequentially. Above them is the executable kernel code, which is of the type EVERYTHING trying to present as a parallel multitasking and other ryushechki. Inside, under the control of the OS kernel, a single-threaded code of node processes, of which we have 8 pieces, is spinning, according to the number of CPU cores.
What will happen to polymers when we get “IO” to the core via the network stack, for example via HTTP? It seems that the OS kernel is coping ...
And if the node has already disposed of everything on all 8 cores? It seems that the OS kernel is also coping ...
But here I would like to look at the benchmark!
Let's do it!
- Let's compare the node with Nginx, as described in the problem above.
- Compare the responsiveness of the node with a full CPU and without it.
I’ll say right away that I ran all the tests for 10 minutes, while doing the usual tasks such as code and surfing.
Yes, in order to make the process work only on certain kernels in Linux, there is a taskset.
In the node, I use it like this:
var PID = process.pid; exec('taskset -pc ' + affinity + ' ' + PID);
I also wrote software for requests on the node via
request.js , it was important not to forget about http.agent.maxSockets. It was possible, of course, CURL, but I wanted to count everything myself.
So, the first test: servers on Nginx and Node, Max 10,000 open requests. In reality, it turned out less, of course. This digit is simply the number of requests in the array of requests and not their actual value per second. It is possible and more requests, but I measured the difference, not performance.
On my hardware, the node sustained more than 1200 responses per second. And nginx withstood them around 3,500.
I understand that such rubbish to someone is not an indicator. But I am very much even an indicator, given that the node's server without any cluster is spinning on the zero core, and the requests are on the first.
Those. the difference is not even orders of magnitude, but only at times!
It is interesting that at first the return gradually increases, then the final figure stabilizes. About three minutes later.
The second test was for the node itself:
| Mode | ~ RPS | ~ PWait | ~ Meme |
one. | When the server node and software requests did not receive affinity at all. | 1400 | 6.5 | 95M |
2 | Server and Requests with affinity from the test with nginx. | ~ 1200-1300 | ~ 5.2 | 85M |
3 | Server with affinity, requests without. | 1100 | ~ 5.5 | 100M |
four. | Server without affinity, requests with it. | 1200 | ~ 6. | 90M |
All measurements of the figures were made visually after 3 minutes of work, when everything is stabilized.
Interestingly, the memory node “intensively eats” at first, then falls a little bit, apparently the collector is working.
~ RPS - roughly Requests Per Second.
~ PWait - approximate page timeout in a real browser. An indirect indicator of system loading when doing something else besides looking at running digits.
For memory, I spied through htop.
Emm - that is, everything is as if in the limit of statistical error.
Just imagine that besides the node there are also DB, redis, HaProxy and Nginx.
+ Business logic is real, not a pair of adders.
Whose will be "sneakers"?
My conclusions for me:
0. Node - already quite good as an interpreter.
- Leave one core of the system itself, if possible.
- Leave more cores to the system if I need to “twist” something else on it.
- The rest can be given to Node servers for 100% recycling.
Git with dough.
Promised Use Case:
- If someone does not know, the installation of dependencies is done as npm install .
- If nothing is changed, then after node test_requester.js, you need to press Enter once to start the queries.
- Stop on Ctrl + C.
- It's all in the console. Offtopic - I use Guake Terminal - IMHO: very convenient.
- The server starts as node test_httpserver.js.
Yes, and do not do tests, if you do not understand the architecture of systems at the iron level. Want to understand - smoke manuals, for example: C. Petzold - “Code. The secret language of computer science. "Everything is detailed there in a very accessible language. I even read her grandfather, and my grandfather is 75 years old and he is a former miner.
Just in case, I will explain - if you have 4 cores, of which real 2, then numCPUs can lie to you mercilessly.
Yes, and my configs, if interested:
cat /etc/sysctl.conffs.file-max = 65535
kernel.max_lock_depth = 4096
fs.mqueue.queues_max = 1024
fs.mqueue.msg_max = 2048
fs.mqueue.msgsize_max = 16384
fs.inotify.max_user_watches = 1048576
fs.inotify.max_queued_events = 65536
fs.inotify.max_user_instances = 16384
net.ipv4.tcp_fin_timeout = 150
kernel.sem = 1000 32000 128 2048
cat /etc/security/limits.confroot hard msgqueue 131072
root soft msgqueue 131072
root hard sigpending 131072
root soft sigpending 131072
root hard nproc 131072
root soft nproc 131072
root hard core 131072
root soft core 131072
root hard nofile 131072
root soft nofile 131072
* hard msgqueue 131072
* soft msgqueue 131072
* hard sigpending 131072
* soft sigpending 131072
* hard nproc 131072
* soft nproc 131072
* hard core 131072
* soft core 131072
* hard nofile 131072
* soft nofile 131072
Checked without these configs, it turned out better by 30 percent....