At Krizalys, we are huge fans of Node.js. We believe it introduced many new concepts that turned web development into a more efficient process and a strong potential to become the leader on the market.
Among other things, Node.js provides an incredible performance, either in rendering pages or actually developing them. This article outlines key performance aspects of Node.js, and in most cases, compare them to a well-known competitor: PHP.
Pages render fast because of...
A monolithic web stack
For modularity reasons, most web frameworks use different software to handle different tasks. For example, a LAMP stack provides, among other things, the Apache web server to handle HTTP traffic and the PHP engine to run web applications.
On the other hand, a Node.js web application typically bundles both the web server and the web application itself. By reducing the overhead of having two software handling different tasks and communicating to each other, this translates to shorter response times.
A "run once" approach
Because a typical Node.js web application bundles a server web, it is designed to never exit. Instead, at the core of the application, you write a callback function to handle incoming HTTP requests, and this function is called as many times as there are requests.
Compare this to PHP applications, where the engine is often running as a CGI for security reasons, and will need to initialize itself, run the code, and deinitialize itself for each request.
A "require once" approach
The fact that Node.js applications never exit has other performance implications. First, whenever it needs to load JavaScript library, it does so only once and may then run its code as many times as needed.
In contrast, in PHP, each request will run the same code to include the same PHP libraries over and over again, and the overall performance of the application is impacted because of the higher I/O operations.
A "connect database and prepare once" approach
Second, for Node.js applications using SQL databases, developers have the ability to connect database servers and prepare SQL queries once, and execute prepared queries multiple times to satisfy multiple the requests. Connecting to database servers only once and running only prepared queries decreases the overhead implied by the database server.
In some SAPIs of PHP, it is not possible to open real persistent connections, and when it is, the database driver has to support it. Furthermore, while it is possible to prepare SQL queries in PHP, if the query is prepared for each request , there are two round-trips to the database server, and unless the query is run multiple times for the same request, there is no real benefit in doing so. Indeed, doing this is even slower than not preparing the query at all.
A true compilation model
Node.js uses the V8 engine to run JavaScript code. This engine gained popularity within desktop browsers mainly because of its speed. The reason why it is so fast is because the engine directly compiles on the fly the JavaScript code into machine code targeted at your CPU. This code is able to run natively without further software assistance, so it runs the fastest.
In PHP and many other scripting languages, the execution process is split in two: compiling to an intermediary bytecode first, and interpret this bytecode by a virtual machine then. While this offers a better portability, the time needed to compile to bytecode is approximately similar to compile to machine code, but in the first case, there is a need to go into a second step of running additional software to actually interpret the bytecode. This is less efficient.
A shorter parsing time
Parsing JavaScript code is fast, partly because, unlike PHP code, the parser does not have to differentiate between HTML markup and actual code. The PHP parser has to be smart, because it needs to differentiate between the embedded HTML markup (or any data outside of PHP tags) and the actual PHP code. Even when you use the PHP engine to run "pure" PHP files, this smart parsing capability is still present in the engine.
But being smart also means running on more support code, and running more code means consuming more CPU cycles. In V8 (and Node.js), on the other hand, the parser is quite lazy and is designed to support only pure JavaScript files, but to do it as fast as possible. Overall, the smart PHP parser is wasting more time than the lazy V8 parser and this will translate to better performance in Node.js.
Development is faster because...
You write code in one language, but run it everywhere
When writing a decent web application, you will have to write JavaScript code at some point. The obvious advantage of using Node.js is the ability to share this code between the server-side and the client-side.
According to the amount of code that may actually be shared between both the server-side and the client-side, it is theoretically possible to divide by up to two the time needed to write an entire web application.
When using any other programming language on the server-side, you expose yourself to the risk of needing to write the same logic in two different languages. Additionally, this makes bugs harder to fix if they have been duplicated on both sides.
You learn one language, but are productive everywhere
Another advantage of using Node.js is that developers need to learn only one programming language before becoming proficient on both the server-side and the client-side. If learning or mastering technologies involved is considered part of the development process, this effectively contributes in decreasing the overall development time.
When using another programming language however, developers will likely need to spend twice more time in learning this language and JavaScript together, since they will have to write JavaScript code at some point, don't forget.