cmorten / opine

Minimalist web framework for Deno ported from ExpressJS.
https://github.com/cmorten/opine/blob/main/.github/API/api.md
MIT License
854 stars 43 forks source link

[REFACTOR] Performance focus #27

Closed asos-craigmorten closed 2 years ago

asos-craigmorten commented 4 years ago

Issue

Setup:

This issue is for first draft performance improvements to Opine.

Details

When first starting out, Opine was up to 2x faster than Express on the benchmarks and a good contender among the other server frameworks Deno currently has on offer.

Given the initial priority of feature parity, performance has been a second class citizen and has suffered, now up to 30% slower than Express in benchmarks.

Ideas welcome for how we can bring the performance back up without compromising the rich set of APIs that the framework has to offer.

Hamza-324 commented 4 years ago

Hello @asos-craigmorten I'm looking for my first contribution on an open-source project, do you think I could help in this issue ?

asos-craigmorten commented 4 years ago

Hey @Hamza-324 👋

It's great that you want to help out!

This particular issue is perhaps not a "good first issue" as is very open ended and investigative, but if you are keen to dive into the code and start coming up with some ideas for improved performance then that would be really awesome! 😄

Hamza-324 commented 4 years ago

@asos-craigmorten sure I'll take a shot at it, any guidelines/tips on how/where to get started ?

asos-craigmorten commented 4 years ago

Hi @Hamza-324, thanks for your patience on me responding!

I guess a good starter for 10 is to clone the repo, pull down locally and check out a few of the examples to get familiar with usage (if you've used Express before then hopefully it feels very familiar!)

Then it's a case of building familiarity with the core code structure. This mirrors the Express 4.x setup with the main entrypoint being the src/opine.ts file which exports the opine() method for creating the application. This particular file is invoked on startup of an application and therefore not something that executes on request to impact performance, but there is some heavy prototype munging that could be impacting perf later on.

Following that check out the src/application.ts. Again this is mostly setup/startup code but it does contain the listen() method which includes the request async iterator - the place we handle all incoming requests.

Requests are handled using app.handle() which subsequently calls router.handle(). This router handling alongside the layer code it invokes is likely the heaviest part of the application and where we potentially lose time, and contains the crucial path matching and subsequent middleware calling logic.

From there it might be worth exploring the remaining files to see how fits together. The last thing any Opine server will do is call res.end()/res.send() so it may be worth checking out src/response.ts for these commonly used methods.

As for tips on where to improve perf - unfortunately haven't got any ideas atm! I've focused mostly on feature richness hence why I raised this issue! I appreciate any thoughts you might have 😄

Hamza-324 commented 4 years ago

@asos-craigmorten No issues and thank you for the detailed run down. I will sit down and work on this and get back to you with my findings.

asos-craigmorten commented 3 years ago

The only other thing worth noting is currently use a Makefile for the commands. Kicking off with a make deps and make build not a bad shout. The benchmarks can then be run using make benchmark (code in the benchmarks directory). The benchmarks make the assumption that you have wrk installed.