JXcore – A Node.JS Distribution with Multi-threading
The modern web is always changing, and this article is more than two years old.
JXcore is a fork on Node.JS 0.12 which is 100% compatible with Node.JS v0.12 and also with all the projects and modules around it.
Using the new multithreaded tasks API, you can simply customize the multithreading feature for your own usage. On the other hand, if you simply want to scale your solution up, the image below shows how easy it is to make your existing Node.JS application multithreaded.
Note: mt-keep:4 means that the process will scale up to 4 threads. It’s up to you to define the best configuration for your servers.
JXcore also includes a proprietary packaging system putting all the sources, assets and dependencies into a single file. This makes JX load faster, consume less heap memory and be easy to deploy.
Here is a list of benefits when using JXcore:
- Achieves multithreading simply by running your application on JXCore;
- Built-in status aware process monitoring, specifically designed for server applications;
- Significant performance gains over Node.JS and Node.JS Cluster as suggested by internal benchmarks;
- Shares the http server load on the native C++ side instead V8 VM (Cluster handles the communication on V8 VM);
- Multithreaded and isolated V8 instances keep V8 GC affecting the responsiveness of the whole process;
- Small memory footprint compared to Node Cluster;
- Automated deployment of Multiple processes with multiple threads behind an auto managed NGINX;
Why We Created JXcore
Node.JS was identified as a great option due to its simplicity, speed of development, active user community, as well as our previous experience with Google’s V8. Despite all these advantages, we had some concerns with overall consistency and efficiency.
Lack of multithreading was the biggest challenge. Not being able to utilize all cores on the servers was a big concern. The closest we could come was Node’s cluster module. This approach required a small update to define what would be done in the main process and its forks. The main process manages the load using fork processes. It can also recover forks when they are closed unexpectedly. It provides a basic level of control over processes and can utilize multiple cores. But there were still number of issues that could not be resolved with the cluster module:
- The host process is not aware of the load on forks;
- Forks are only useful when the host process is functioning;
- Expensive memory usage;
- Duplication of the whole process without optimizing the usage (waste of CPU cycles);
- Inconsistent behavior on Windows compared to *ix platforms.
Running Node.JS in multiple contexts helps native add-ons switching between separate V8 contexts. Indeed, this feature is quite useful for the scenarios requiring context safety. On the other hand, it surely has a performance impact on the entire application. Switching among the V8 contexts has no benefit with the heap limits or performance numbers. The solution is still limited to a single thread. While some people recommend a single thread as beneficial, our internal tests showed that switching to multithreaded isolates brought more than 45% solid performance improvements. We developed our backend solution as single thread in mind but used our multithreaded Node.JS distribution to attain benefits from all the available cores.
Packaging & Code Security
Based on our past experience, most enterprise customers require offline installation without online dependencies. Considering the current package manager of Node.JS, we needed to implement a fully featured packaging tool that would keep all the dependencies together without requiring extra steps. We also wanted to provide a framework so that we could allow our developers to monetize their add-on work.
We were either going to accept the limitations of Node.JS with respect to our project or choose a different development platform. We decided to work on Node’s core library and see if we could change it enough to meet our requirements. We also knew that there was an attempt in the past by Node’s core contributors to make it multithreaded but it was abandoned.
After months of extensive development in Node’s core libraries and dependencies, we have achieved what we had set out to do. Unfortunately, the addition of our requirements called for major architectural changes in Node. The result was a major fork on Node project that we named JXcore. However, we are committed to keeping JXCore 100% compatible with all other Node.JS modules that work with the latest version of Node.JS available.
What’s Next with JXcore?
You can download and try JXCore here.