BackendStack21 / restana

Restana is a lightweight and fast Node.js framework for building RESTful APIs.
MIT License
467 stars 27 forks source link

Upgrading router #12

Closed amitguptagwl closed 5 years ago

amitguptagwl commented 5 years ago

Disclaimer: I'm the author of Anumargak package.

I would like you to have a look on anumargak router which may increase the speed of restana. Here is the comparison;

chart

Anumargak supports some additional features.

jkyberneees commented 5 years ago

I will extend restana to allow factory based router injection, so we can use Anumargak or any other compatible router. So, prepare to challenge the current benchmarks 😎 Thanks

jkyberneees commented 5 years ago

Hi Amit, as requested, restana now allows router override in v2.7.0. Please see more details here: https://github.com/jkyberneees/ana/pull/13 An example is also available here: https://github.com/jkyberneees/ana/blob/master/demos/router-factory.js Would you like to provide some benchmarks? Docs here: https://www.npmjs.com/package/restana#providing-a-router-factory-method Thanks

amitguptagwl commented 5 years ago

Thanks for the changes. I'll update you.

amitguptagwl commented 5 years ago

So I've tested with following configuration;

Setup

Anumargak

const anumargak = require('anumargak')
const service = require('restana')({
  routerFactory: (options) => {
    return anumargak(options)
  }
})

service.get("/this/is/static", function(req, res){
    res.send("Hello");
})

service.get("/this/is/:dynamic", function(req, res){
    res.send("Hello");
})

//commented for apple-to-apple comparison
/* service.get("/this/is/:enum(this|that)", function(req, res){
    res.send("Hello");
}) */

service.start(3001).then((server) => {
    console.log("server has been started on port 3001")
});

Find-my-way

const service = require('restana')({});

service.get("/this/is/static/only", function(req, res){
    res.send("Hello");
})

service.get("/this/is/:dynamic", function(req, res){
    res.send("Hello");
})

//commented because multiple similar dynamic routes are not supported
/* service.get("/this/is/:enum(this|that)", function(req, res){
    res.send("Hello");
}) */

service.start(3000).then((server) => {
    console.log("server has been started on port 3000")
});

Benchmark

https://github.com/node-muneem/anumargak/tree/master/benchmark/framework

Run 1

Running restana with find-my-way
server has been started on port 3000
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Completed 25000 requests
Completed 30000 requests
Completed 35000 requests
Completed 40000 requests
Completed 45000 requests
Completed 50000 requests
Finished 50000 requests
Requests per second:    21686.82 [#/sec] (mean)
Running restana with anumargak
server has been started on port 3001
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Completed 25000 requests
Completed 30000 requests
Completed 35000 requests
Completed 40000 requests
Completed 45000 requests
Completed 50000 requests
Finished 50000 requests
Requests per second:    22287.71 [#/sec] (mean)

Run 2

I've added more routes and still there was not much difference

Running restana with find-my-way
:
Requests per second:    21953.28 [#/sec] (mean)
Running restana with anumargak
:
Requests per second:    22302.63 [#/sec] (mean)

Run 3

This time I'm running the tests for dynamic URL. But it was not big difference

Running restana with find-my-way
:
Requests per second:    21599.56 [#/sec] (mean)
Running restana with anumargak
:
Requests per second:    22254.75 [#/sec] (mean)

Run 4

This time I tested anumargak and find-my-way directly. And I've realized as there are multiple features have been added to anumargak, it is better than find-my-way in case of static and enumerated URLs but not better in case of dynamic URLs.

Anumargak static : 4758364.940228024 requests/second
find my way static : 4701790.601081763 requests/second
Anumargak dynamic : 1183718.6619436215 requests/second
find my way dynamic : 1413701.2189737826 requests/second
Anumargak enum : 4082851.9965513186 requests/second
find my way enum : 1431152.4839272124 requests/second
Anumargak wildchar : 1362545.4774191594 requests/second
find my way wildchar : 1421189.5269839475 requests/second
Anumargak versioned/static : 653232.2387602883 requests/second
find my way versioned/static : NOT SUPPORTED
Anumargak versioned/dynamic : 274372.3184456422 requests/second
find my way versioned/dynamic : 297072.75524877565 requests/second

Run 5

All previous tests were run on node v10.10 and npm 6.4. So I'v upgraded them to node v11.6 and npm v6.5.

Running restana with find-my-way
:
Requests per second:    19343.97 [#/sec] (mean)
Running restana with anumargak
:
Requests per second:    20954.03 [#/sec] (mean)

not much difference

Hardware

I've performed these tests on Ubuntu 17.10 i7 with 16GB RAM. However, there around 40 firefox tabs, 7 vscode windows are also open.

amitguptagwl commented 5 years ago

I've run one more test for my curiosity. But, this time, I included muneem framework.

Running restana with find-my-way
:
Requests per second:    21208.09 [#/sec] (mean)
Running restana with anumargak
:
Requests per second:    22037.26 [#/sec] (mean)
Running muneem
:
Requests per second:    26716.78 [#/sec] (mean)

Muneem doesn't leverage all the benefits of anumargak. I was expecting it to be slower because it does so many things in the background for security and automate things. And it is unfair to compare muneem with any framework for speed because this is not its motive. I've created muneem to reduce documentation and increase security.

But unexpectedly it was faster in these tests.

jkyberneees commented 5 years ago

Hi Amit, thanks a lot for your exhaustive perf testing here. I can confirm your findings, as I also tested on my side. As a hint, when I tweaked your router to disable the versions support, it was as fast as find-my-way, I guess there is still room for improvements. Other than that, anumargak is still really fast, I am happy that it has become an option in restana. Thanks. Maybe an article here explaining the features and benefits would help on its adoption.

Regarding restana performance with find-my-way, please consider that restana uses as much CPU as it can by default; under low resources, better you disable "prioRequestsProcessing".

I would love if you can add muneem to this list: https://github.com/the-benchmarker/web-frameworks, maybe it becomes the framework to beat ;)

Let's keep in contact.

amitguptagwl commented 5 years ago

First of all, I would like to appreciate your behavior to support the work of other developers. Otherwise, many developers ignore it and see it as a competition. :clap:

As a hint, when I tweaked your router to disable the versions support, it was as fast as find-my-way, I guess there is still room for improvements.

I believe you mean dynamic URLs. Yes, I agree improvements can be done. And I'll try to focus on them as soon as I get some time. There are some features like the list of handlers seem useless and impact the performance. So need a plan what to keep in and what to kick out.

Maybe an article here explaining the features and benefits would help on its adoption.

I've added the integration example from above comments to anumargark's github page. Will think to write an article in the future.

I would love if you can add muneem to this list: https://github.com/the-benchmarker/web-frameworks, maybe it becomes the framework to beat ;)

Thanks. Done

amitguptagwl commented 5 years ago

I've done some changes to anumargak to make it slightly fast. previously it was

Anumargak static : 4758364.940228024 requests/second
find my way static : 4701790.601081763 requests/second

now it is

Anumargak static : 9550021.43323372 requests/second
find my way static : 5976195.8194932435 requests/second

we can improve it further by indexing and implementing parse tree for dynamic routes. But I doubt we need that much speed. So I've written an article with the experience I had here.

https://medium.com/@amitgupta.gwl/a-quick-guide-to-select-a-router-for-a-node-js-application-62c682e40afa

jkyberneees commented 5 years ago

Thanks Amit, will check it and update you accordingly.

Off topic: You may be interested: https://github.com/jkyberneees/middleware-if-unless, it can also be used with anumargak.