Skip to content
This repository has been archived by the owner on May 3, 2024. It is now read-only.

Feat: ExpressJS to Fastify migration #938

Merged
merged 32 commits into from
Mar 6, 2023
Merged

Conversation

giulianok
Copy link
Member

ExpressJS to Fastify migration. This is an internal change, API isn't being impacted.

Note: bringing fastify back to main after we reverted it and made it an experiment for more testing

Description

Migrating away from ExpressJS to improve performance, essentially be able to reduce time-to-start resolving a request, time-to-response, and handle more requests per second.

Small PRs have been raised for the team to easily review the changes:
#854
#856
#857
#859
#860
#865

This PR is the result of all these small PRs

Metrics

Fastify benchmark

Running 10s test @ http://localhost:3000/_/status (simple status check)
10 connections
┌─────────┬──────┬──────┬───────┬──────┬────────┬─────────┬───────┐
│ Stat    │ 2.5% │ 50%  │ 97.5% │ 99%  │ Avg    │ Stdev   │ Max   │
├─────────┼──────┼──────┼───────┼──────┼────────┼─────────┼───────┤
│ Latency │ 0 ms │ 0 ms │ 3 ms  │ 3 ms │ 0.6 ms │ 0.89 ms │ 32 ms │
└─────────┴──────┴──────┴───────┴──────┴────────┴─────────┴───────┘
┌───────────┬────────┬────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ Stat      │ 1%     │ 2.5%   │ 50%     │ 97.5%   │ Avg     │ Stdev   │ Min     │
├───────────┼────────┼────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Req/Sec   │ 4167   │ 4167   │ 8287    │ 8799    │ 7915.6  │ 1290.37 │ 4165    │
├───────────┼────────┼────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Bytes/Sec │ 2.1 MB │ 2.1 MB │ 4.17 MB │ 4.43 MB │ 3.98 MB │ 649 kB  │ 2.09 MB │
└───────────┴────────┴────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
Req/Bytes counts sampled once per second.
# of samples: 10
79k requests in 10.03s, 39.8 MB read
-------------------------------------------------------------------------------------
Running 10s test @ http://localhost:3000/html-partial/en-US/frank-the-parrot (HTML Partial)
10 connections
┌─────────┬──────┬───────┬───────┬───────┬──────────┬─────────┬───────┐
│ Stat    │ 2.5% │ 50%   │ 97.5% │ 99%   │ Avg      │ Stdev   │ Max   │
├─────────┼──────┼───────┼───────┼───────┼──────────┼─────────┼───────┤
│ Latency │ 9 ms │ 13 ms │ 31 ms │ 35 ms │ 14.81 ms │ 6.09 ms │ 75 ms │
└─────────┴──────┴───────┴───────┴───────┴──────────┴─────────┴───────┘
┌───────────┬────────┬────────┬────────┬─────────┬────────┬────────┬────────┐
│ Stat      │ 1%     │ 2.5%   │ 50%    │ 97.5%   │ Avg    │ Stdev  │ Min    │
├───────────┼────────┼────────┼────────┼─────────┼────────┼────────┼────────┤
│ Req/Sec   │ 412    │ 412    │ 627    │ 771     │ 653.3  │ 106.24 │ 412    │
├───────────┼────────┼────────┼────────┼─────────┼────────┼────────┼────────┤
│ Bytes/Sec │ 540 kB │ 540 kB │ 822 kB │ 1.01 MB │ 856 kB │ 139 kB │ 540 kB │
└───────────┴────────┴────────┴────────┴─────────┴────────┴────────┴────────┘
Req/Bytes counts sampled once per second.
# of samples: 10
7k requests in 10.02s, 8.56 MB read
-------------------------------------------------------------------------------------
Running 10s test @ http://localhost:3000/vitruvius (Full HTML Render)
10 connections
┌─────────┬───────┬───────┬───────┬───────┬──────────┬─────────┬───────┐
│ Stat    │ 2.5%  │ 50%   │ 97.5% │ 99%   │ Avg      │ Stdev   │ Max   │
├─────────┼───────┼───────┼───────┼───────┼──────────┼─────────┼───────┤
│ Latency │ 10 ms │ 14 ms │ 33 ms │ 37 ms │ 16.39 ms │ 6.07 ms │ 65 ms │
└─────────┴───────┴───────┴───────┴───────┴──────────┴─────────┴───────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬────────┬─────────┐
│ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%   │ Avg     │ Stdev  │ Min     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Req/Sec   │ 419     │ 419     │ 603     │ 659     │ 591.3   │ 68.74  │ 419     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Bytes/Sec │ 4.15 MB │ 4.15 MB │ 5.97 MB │ 6.52 MB │ 5.85 MB │ 680 kB │ 4.14 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴────────┴─────────┘
Req/Bytes counts sampled once per second.
# of samples: 10
6k requests in 10.02s, 58.5 MB read

Fastify runner + ExpressJS routes & logic (current implementation)

Running 10s test @ http://localhost:3000/_/status (simple status check)
10 connections
┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬───────┐
│ Stat    │ 2.5% │ 50%  │ 97.5% │ 99%  │ Avg     │ Stdev   │ Max   │
├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼───────┤
│ Latency │ 1 ms │ 2 ms │ 5 ms  │ 7 ms │ 2.39 ms │ 1.08 ms │ 22 ms │
└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴───────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬────────┬─────────┐
│ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%   │ Avg     │ Stdev  │ Min     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Req/Sec   │ 2331    │ 2331    │ 3673    │ 4223    │ 3599.55 │ 538.4  │ 2330    │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Bytes/Sec │ 1.04 MB │ 1.04 MB │ 1.64 MB │ 1.88 MB │ 1.61 MB │ 240 kB │ 1.04 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴────────┴─────────┘
Req/Bytes counts sampled once per second.
# of samples: 11
40k requests in 11.02s, 17.7 MB read
-------------------------------------------------------------------------------------
Running 10s test @ http://localhost:3000/html-partial/en-US/frank-the-parrot (HTML Partial)
10 connections
┌─────────┬───────┬───────┬───────┬───────┬──────────┬─────────┬───────┐
│ Stat    │ 2.5%  │ 50%   │ 97.5% │ 99%   │ Avg      │ Stdev   │ Max   │
├─────────┼───────┼───────┼───────┼───────┼──────────┼─────────┼───────┤
│ Latency │ 11 ms │ 17 ms │ 37 ms │ 41 ms │ 18.54 ms │ 6.77 ms │ 82 ms │
└─────────┴───────┴───────┴───────┴───────┴──────────┴─────────┴───────┘
┌───────────┬────────┬────────┬────────┬────────┬────────┬─────────┬────────┐
│ Stat      │ 1%     │ 2.5%   │ 50%    │ 97.5%  │ Avg    │ Stdev   │ Min    │
├───────────┼────────┼────────┼────────┼────────┼────────┼─────────┼────────┤
│ Req/Sec   │ 373    │ 373    │ 521    │ 620    │ 524.9  │ 63.13   │ 373    │
├───────────┼────────┼────────┼────────┼────────┼────────┼─────────┼────────┤
│ Bytes/Sec │ 494 kB │ 494 kB │ 690 kB │ 821 kB │ 695 kB │ 83.6 kB │ 494 kB │
└───────────┴────────┴────────┴────────┴────────┴────────┴─────────┴────────┘
Req/Bytes counts sampled once per second.
# of samples: 10
5k requests in 10.02s, 6.95 MB read
-------------------------------------------------------------------------------------
Running 10s test @ http://localhost:3000/vitruvius (Full HTML Render)
10 connections
┌─────────┬───────┬───────┬───────┬───────┬──────────┬─────────┬───────┐
│ Stat    │ 2.5%  │ 50%   │ 97.5% │ 99%   │ Avg      │ Stdev   │ Max   │
├─────────┼───────┼───────┼───────┼───────┼──────────┼─────────┼───────┤
│ Latency │ 12 ms │ 18 ms │ 39 ms │ 44 ms │ 19.85 ms │ 7.06 ms │ 76 ms │
└─────────┴───────┴───────┴───────┴───────┴──────────┴─────────┴───────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬────────┬─────────┐
│ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%   │ Avg     │ Stdev  │ Min     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Req/Sec   │ 355     │ 355     │ 508     │ 553     │ 491     │ 51.83  │ 355     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Bytes/Sec │ 3.51 MB │ 3.51 MB │ 5.02 MB │ 5.47 MB │ 4.85 MB │ 513 kB │ 3.51 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴────────┴─────────┘
Req/Bytes counts sampled once per second.
# of samples: 10
5k requests in 10.03s, 48.5 MB read

ExpressJS only

This is just to provide some context of the Fastify improvement so far

Running 10s test @ http://localhost:3000/_/status
10 connections
┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬───────┐
│ Stat    │ 2.5% │ 50%  │ 97.5% │ 99%  │ Avg     │ Stdev   │ Max   │
├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼───────┤
│ Latency │ 1 ms │ 2 ms │ 6 ms  │ 7 ms │ 2.53 ms │ 1.24 ms │ 25 ms │
└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴───────┘
┌───────────┬────────┬────────┬─────────┬─────────┬─────────┬────────┬────────┐
│ Stat      │ 1%     │ 2.5%   │ 50%     │ 97.5%   │ Avg     │ Stdev  │ Min    │
├───────────┼────────┼────────┼─────────┼─────────┼─────────┼────────┼────────┤
│ Req/Sec   │ 2213   │ 2213   │ 3459    │ 3829    │ 3393.4  │ 445.87 │ 2213   │
├───────────┼────────┼────────┼─────────┼─────────┼─────────┼────────┼────────┤
│ Bytes/Sec │ 987 kB │ 987 kB │ 1.54 MB │ 1.71 MB │ 1.51 MB │ 199 kB │ 987 kB │
└───────────┴────────┴────────┴─────────┴─────────┴─────────┴────────┴────────┘
Req/Bytes counts sampled once per second.
# of samples: 10
34k requests in 10.02s, 15.1 MB read
Running 10s test @ http://localhost:3000/html-partial/en-US/frank-the-parrot
10 connections
┌─────────┬───────┬───────┬───────┬───────┬─────────┬─────────┬───────┐
│ Stat    │ 2.5%  │ 50%   │ 97.5% │ 99%   │ Avg     │ Stdev   │ Max   │
├─────────┼───────┼───────┼───────┼───────┼─────────┼─────────┼───────┤
│ Latency │ 12 ms │ 16 ms │ 36 ms │ 41 ms │ 18.2 ms │ 6.62 ms │ 97 ms │
└─────────┴───────┴───────┴───────┴───────┴─────────┴─────────┴───────┘
┌───────────┬────────┬────────┬────────┬────────┬────────┬─────────┬────────┐
│ Stat      │ 1%     │ 2.5%   │ 50%    │ 97.5%  │ Avg    │ Stdev   │ Min    │
├───────────┼────────┼────────┼────────┼────────┼────────┼─────────┼────────┤
│ Req/Sec   │ 350    │ 350    │ 556    │ 616    │ 534.1  │ 75.15   │ 350    │
├───────────┼────────┼────────┼────────┼────────┼────────┼─────────┼────────┤
│ Bytes/Sec │ 442 kB │ 442 kB │ 701 kB │ 777 kB │ 673 kB │ 94.7 kB │ 441 kB │
└───────────┴────────┴────────┴────────┴────────┴────────┴─────────┴────────┘
Req/Bytes counts sampled once per second.
# of samples: 10
5k requests in 10.02s, 6.74 MB read
Running 10s test @ http://localhost:3000/vitruvius
10 connections
┌─────────┬───────┬───────┬───────┬───────┬──────────┬─────────┬───────┐
│ Stat    │ 2.5%  │ 50%   │ 97.5% │ 99%   │ Avg      │ Stdev   │ Max   │
├─────────┼───────┼───────┼───────┼───────┼──────────┼─────────┼───────┤
│ Latency │ 13 ms │ 18 ms │ 39 ms │ 43 ms │ 20.21 ms │ 7.11 ms │ 80 ms │
└─────────┴───────┴───────┴───────┴───────┴──────────┴─────────┴───────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬────────┬─────────┐
│ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%   │ Avg     │ Stdev  │ Min     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Req/Sec   │ 331     │ 331     │ 493     │ 538     │ 482.3   │ 57.01  │ 331     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Bytes/Sec │ 3.25 MB │ 3.25 MB │ 4.85 MB │ 5.29 MB │ 4.74 MB │ 560 kB │ 3.25 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴────────┴─────────┘
Req/Bytes counts sampled once per second.
# of samples: 10
5k requests in 10.02s, 47.4 MB read

Motivation and Context

It improves requests performance

How Has This Been Tested?

Types of Changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation (adding or updating documentation)
  • Dependency update
  • Security update

Checklist:

  • My change requires a change to the documentation and I have updated the documentation accordingly.
  • These changes should be applied to a maintenance branch.
  • This change requires cross browser checks.
  • Performance tests should be ran against the server prior to merging.
  • This change impacts caching for client browsers.
  • This change impacts HTTP headers.
  • This change adds additional environment variable requirements for One App users.
  • I have added the Apache 2.0 license header to any new files created.

What is the Impact to Developers Using One App?

giulianok and others added 29 commits December 5, 2022 07:15
feat: migrated express to fastify
feat(fastifycdn): migrate holocron cdn to fastify
fix: matching headers with existing express output
fix: exposing request and reply objects instead of raw
@giulianok giulianok requested a review from a team as a code owner March 2, 2023 15:54
@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2023

Size Change: +2.52 kB (0%)

Total Size: 687 kB

Filename Size Change
./build/app/app.js 164 kB -1.63 kB (-1%)
./build/app/app~vendors.js 389 kB +1.18 kB (0%)
./build/app/service-worker-client.js 7.26 kB -3 B (0%)
./build/app/vendors.js 120 kB +2.98 kB (+3%)
ℹ️ View Unchanged
Filename Size
./build/app/runtime.js 7.07 kB

compressed-size-action

Matthew-Mallimo
Matthew-Mallimo previously approved these changes Mar 2, 2023
@Matthew-Mallimo Matthew-Mallimo requested a review from a team March 2, 2023 21:46
@Matthew-Mallimo Matthew-Mallimo requested a review from a team March 6, 2023 19:49
@10xLaCroixDrinker 10xLaCroixDrinker merged commit 9b0c4b3 into main Mar 6, 2023
@10xLaCroixDrinker 10xLaCroixDrinker deleted the experimental/fastify branch March 6, 2023 20:15
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants