Handling out of memory errors is a hard problem. At the point when you can't allocate more memory you are busted in most languages. For example in C a slightly deeper function call depth can cause the stack to expand at any point. If that point coincides with you running out of memory then you are busted. No program can keep running with a broken stack.
If V8 were capable of recovering from out-of-memory errors then you would still have to go through all of node and all the native libraries that it uses and check that they can handle any allocation failing.
And if V8 handled out-of-memory errors with exceptions then you have two choices. Either make the exceptions uncatchable, in which case the JS program running in the server has no way to recover and is probably in an inconsistent state. Or make the exceptions catchable, in which case there is no guarantee that any memory will ever be freed up and you are back to square one.
I think it's possible to make V8 more resistant to out of memory situations. I don't think it's possible to make it bulletproof, and I don't think there are many server apps that have this property. Do people run Java servers in such a way that they are often getting out of memory exceptions, recovering, and then continuing to serve? I don't think so.
In practice the way most servers work is that you give them plenty of memory and you write your server app in such a way that it does not use unlimited memory.
If there are non-out-of-memory errors that V8 is failing to recover from then these are bugs and should be reported. I can't think of any examples off-hand.
As far as the other comments go they seem to assume that you will want to use a V8 context per connection. Node uses one V8 context for all connections, so the comments don't apply. Context creation has been speeded up a lot since the article was written, but this is only for the browser. Node doesn't need it.
You're being too clever - if you run out of memory, throw away the request and all associated resources and return "500: Internal server error". There are lots of reasons why this isn't perfect (if the OS overcommits memory, like Linux (typically?) does, it will have to kill you to avoid running out; if you need to use swap you're too slow to be useful; etc), but it's not impossible.
node.js (one process for many requests) is a different model than the author is considering; no matter its (dis)advantages, integrating it into the server is not nearly as advantageous as for a process-per-request model (like mod_php).
From a service perspective, I'd prefer to have the process crash and supervisor restart it. Returning HTTP/500 errors on memory allocation failures (which usually last until the process is restarted anyway) is likely to deny service to a larger number of users.
Overcommit seems to have changed somewhat since the "early days," as it's now heuristic. I ran into this once when I couldn't malloc 8 GB on a 64-bit machine because RAM + swap was less than 8 GB. http://www.mjmwired.net/kernel/Documentation/vm/overcommit-a...
If you are using GBs of Heap space, GC pauses are going to make you cry before you worry about an OOM error. More, smaller processes are the way to go for a number of reasons (recovery is cheaper when you lose smaller things..)
Sysoev brings up a couple good points that affect Node.js .
1) The fact memory allocation might crash the process is a serious problem. Is this still the case?
2) The fact that garbage collection is still stop-the-world may be a problem for server availability. Are we able to call the generational collector from node, or no?
Things that don't involve node:
The ability to create multiple objects in different contexts. Sysoev is thinking of the "scripting" model, like PHP, which is not how Node does things. Node just runs one process to handle thousands of requests, not thousands of processes or threads. There is no need.
That's incredible. When I read the article I didn't realize I'm reading google translated version, so I thought "Igor's english is a bit broken but relatively good". I only realized I read a translation when you pointed it out. I went back to re-read the original (I'm a native russian speaker) and it's amazing how close google got to expressing the essence of every sentence.
Not only is the translation of a surprisingly high quality, but reading the original in Russian is more awkward since a lot of the technical terms are originally English. I needed to read a particular portion 3 times before I realized it meant memory allocation.
I though the same thing. I learned all the tech terms in English, so when I read "sborka musora" instead of "garbage collection" it somehow makes me smile.
Technical texts like this are relatively easy to get right. English is not my native language and when I was young I could read computer related stuff, but had trouble understanding, for example Harry Potter. If Google has an example of such a text, they can learn all the translations for all the technical terms from that data. However, a news article is much more difficult because they often have lot's of metaphors, etc. If you try to translate those, you get a lot of halve finished sentences and stuff like that.
Indeed. However though Google translate quite correctly from most common languages to English, translation to other languages (even English to French or English to Spanish) often hardly makes any sense.
Haha, I thought your reply was talking about how the V8 engine worked(translating to machine specific code), instead of the language translator used on the blog post.
It likely was not completely translated by machine. Google Translate lets anyone reading the translation edit it to fix errors. Highlight some text and notice the link that appears allowing you to "Contribute a better translation" for that particular passage.
It's more likely that it only helps train Google Translate, and doesn't actually apply any changes directly to the translated text. Otherwise vandalism would be way too easy.
The thing that led me to it was halfway through, when I moved the cursor on top of the text and there was some popup, at which point I yelled, WTH is that crap site with some broken JS advertising! I moved the mouse away but kept moving it in by pure reflex. It took me a whole minute to realize it was Google Translate.
Before I actually noticed that, "snapshot'ov" actually made me laughed, genuinely (mis)taking it for some sort of pun.
I still remember being able to play a game with one of my friends where we'd translate a sentence to German then back to English and laugh at how mangled it was…
"Number of games: We, and I have learned how to use the means for translating the German text in English is still a way of encoding their friends to play with a smile. .."
While an interesting article in its own right, it has nothing to do with node.js, except that this happens to be a criticism of the way V8 works, which node.js is built on. However, they may not be using things in the same way he is, or there could be mitigating circumstances which make it possible for node.js to pull this off. (I don't know anything about node.js internals, I just know this article isn't about it, as the title indicates.)
Edit: This was written when the title was "The author of Nginx on node.js and why V8 is not suitable for web servers". It's since been changed.
I disagree. Where V8 can run is a core part of the deployment surface of node.js, so what server authors think about V8 and it's suitability for integration and deployment very much matter to node.js.
Agreed. The title is totally trolling for attention.
Nginx and Nodejs are very different. Nodejs was built on V8 from the beginning, while it would have to be grafted into Nginx somehow. Nodejs isn't Chrome but it's willing to pretend that it is - nginx isn't.
The title is a copy from a Reddit posting. I thought about changing it. Node.js is build on top of V8. It is better to get attention from Node.js experts so that others can get a clearer picture. Updated: Never mind, someone just change the title for me. The original title is "The author of Nginx on node.js and why V8 is not suitable for web servers.".
Right, this definitely seemed more like an article on V8 than on node.js. Though to be fair, the platform running node is arguably very important to node's implementation.
At Microsoft, I watched (from afar) the incredibly painful multi-year process of making a complex language runtime intended for one environment (.NET for IIS) satisfy the requirements of a very different environment (SQL Server). When fundamental design assumptions like "memory allocation failures can kill the process" have to change, it's a big deal.
Seems like process isolation a la fastcgi is the practical way to go, unless the V8 team itself wants V8 to be embeddable in a "reliable" way (meaning, it recovers from its own errors without corrupting the process it's embedded in).
Node.js is often used because it is cool, new and easier for front-end developers to develop a functioning backend.
For more traditional uses that want something less hackish, erlang for example, crashes only a single thread not the entire vm. Functional programming languages in general like haskell and erlang are interesting for backend core services.
The state of todays base of node (v8) has nothing to do with the concept/paradigm its trying to put forward -- that is event driven web apps. Hence, one must not discard node as a bad solution only because v8 is not optimal in all situations.
These only sound like problems if you need to keep it single process. If you break out the javascript interpreter via fastcgi workers just like people do with php on nginx it becomes mostly moot points right? At that point its limited to 500 req/sec/core, but frankly these days that means 4000 req/s, which, hell, I'll take it.
Granted thats assuming you can actually run a fastcgi/v8 setup, I've never looked. I wonder how hard a mod_v8 for apache prefork would be.
As I'm sure others will point out, this article has less to do with node.js as it does with embedding v8 in Nginx. Although since node.js runs in v8, I suppose you could interpret it that way.
IIRC, on Linux at least the memory allocation thing is moot. If your process runs out of memory, it dies anyway. You can't catch "malloc says no" because malloc never says no. It either says yes or blows your process's brains out.
malloc says no if you set a ulimit in your shell. I do this on the desktop to stop myself from shooting myself in the foot. (Recent kernels also let you turn off the overcommitting behavior.)
A lot of the points raised are an issue only for long running processes. Akshell (http://www.akshell.com), for example, has synchronous I/O libraries and uses an Apache MPM like model, so for us the limits are less of a concern.
I keep seeing these replies on how well Google Translate performed. I didn't realize while reading that it was machine-translated, but my immediate thought was "this person is not a native English speaker or needs much work his attempt at Yoda-speak does."
But still understandable, so that's a success I'd say.
I remember when nginx first came out (the web server that the author built) and the biggest barrier to adoption was the fact that all the documentation was in russian. Online machine translation did not produce understandable content at that time.
it's a great write up and the context issue seems interesting, however it's from Feb 2010 according to the last paragraph and a lot has changed in V8 since
A thought: why not have node developers fork V8, and modify that to make it ready for server deployment? Has the coreteam and/or Dahl thought about this?
It sounds like more of the concern is that V8 is/was buggy & had some situations where performance would be compromised. I don't think it's a slam saying it could never be used.
Handling out of memory errors is a hard problem. At the point when you can't allocate more memory you are busted in most languages. For example in C a slightly deeper function call depth can cause the stack to expand at any point. If that point coincides with you running out of memory then you are busted. No program can keep running with a broken stack.
If V8 were capable of recovering from out-of-memory errors then you would still have to go through all of node and all the native libraries that it uses and check that they can handle any allocation failing.
And if V8 handled out-of-memory errors with exceptions then you have two choices. Either make the exceptions uncatchable, in which case the JS program running in the server has no way to recover and is probably in an inconsistent state. Or make the exceptions catchable, in which case there is no guarantee that any memory will ever be freed up and you are back to square one.
I think it's possible to make V8 more resistant to out of memory situations. I don't think it's possible to make it bulletproof, and I don't think there are many server apps that have this property. Do people run Java servers in such a way that they are often getting out of memory exceptions, recovering, and then continuing to serve? I don't think so.
In practice the way most servers work is that you give them plenty of memory and you write your server app in such a way that it does not use unlimited memory.
If there are non-out-of-memory errors that V8 is failing to recover from then these are bugs and should be reported. I can't think of any examples off-hand.
As far as the other comments go they seem to assume that you will want to use a V8 context per connection. Node uses one V8 context for all connections, so the comments don't apply. Context creation has been speeded up a lot since the article was written, but this is only for the browser. Node doesn't need it.