Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: Optimize resolving X-Forwarded-For addresses #5458

Merged
merged 4 commits into from May 15, 2024

Conversation

dmkng
Copy link
Contributor

@dmkng dmkng commented May 10, 2024

Hello, I have a suggestion. When looking up how trustProxy option in Fastify works in detail, I found out that the proxy-addr dependency used by Fastify, specifically the .all() function, checks if the trust argument is provided, and if it's not, then it just returns all adresses, skipping the trust checking logic alltogether, which can speed up things greatly, especially if there's a lot of X-Forwarded-For addresses. So, I made this PR, replacing the return true function with undefined, which has the same effect in the .ips property getter of Request, but because the proxy-addr default function doesn't support skipping trust argument, I replaced it with proxy-addr .all() function in the .ip property getter and did the same thing there as the proxy-addr default function does, so everything behaves exactly the same as before. If something needs further explanation please let me know.

Checklist

dmkng added 2 commits May 10, 2024 12:16
Signed-off-by: Susan <25956407+dmkng@users.noreply.github.com>
Signed-off-by: Susan <25956407+dmkng@users.noreply.github.com>
@dmkng dmkng changed the title Optimize resolving X-Forwarded-For addresses perf: Optimize resolving X-Forwarded-For addresses May 10, 2024
@mcollina
Copy link
Member

can you adjust the pr title according to the rules?

@mcollina
Copy link
Member

how much perf does this give us?

@dmkng
Copy link
Contributor Author

dmkng commented May 10, 2024

can you adjust the pr title according to the rules?

I added perf: at the beggining, is there something else to adjust?

how much perf does this give us?

I made a simple test that sends 11 addresses in X-Forwarded-For to the Fastify server with trustProxy: true and a single endpoint printing .ip and .ips properties of Request, I can add it to the PR or to the separate branch of my fork.

Without the optimization:

[1] Running 30s test @ http://localhost:3000/
[1] 100 connections with 10 pipelining factor
[1]
[1]
[1] ┌─────────┬───────┬───────┬───────┬───────┬──────────┬──────────┬────────┐
[1] │ Stat    │ 2.5%  │ 50%   │ 97.5% │ 99%   │ Avg      │ Stdev    │ Max    │
[1] ├─────────┼───────┼───────┼───────┼───────┼──────────┼──────────┼────────┤
[1] │ Latency │ 23 ms │ 26 ms │ 34 ms │ 83 ms │ 27.37 ms │ 14.94 ms │ 402 ms │
[1] └─────────┴───────┴───────┴───────┴───────┴──────────┴──────────┴────────┘
[1] ┌───────────┬─────────┬─────────┬─────────┬────────┬──────────┬─────────┬─────────┐
[1] │ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%  │ Avg      │ Stdev   │ Min     │
[1] ├───────────┼─────────┼─────────┼─────────┼────────┼──────────┼─────────┼─────────┤
[1] │ Req/Sec   │ 26 415  │ 26 415  │ 37 055  │ 37 503 │ 35 877,6 │ 2460,9  │ 26 404  │
[1] ├───────────┼─────────┼─────────┼─────────┼────────┼──────────┼─────────┼─────────┤
[1] │ Bytes/Sec │ 12.7 MB │ 12.7 MB │ 17.8 MB │ 18 MB  │ 17.2 MB  │ 1.18 MB │ 12.7 MB │
[1] └───────────┴─────────┴─────────┴─────────┴────────┴──────────┴─────────┴─────────┘
[1]
[1] Req/Bytes counts sampled once per second.
[1] # of samples: 30
[1]
[1] 1077k requests in 30.05s, 516 MB read

With the optimization:

[1] Running 30s test @ http://localhost:3000/
[1] 100 connections with 10 pipelining factor
[1]
[1]
[1] ┌─────────┬───────┬───────┬───────┬───────┬──────────┬──────────┬────────┐
[1] │ Stat    │ 2.5%  │ 50%   │ 97.5% │ 99%   │ Avg      │ Stdev    │ Max    │
[1] ├─────────┼───────┼───────┼───────┼───────┼──────────┼──────────┼────────┤
[1] │ Latency │ 22 ms │ 25 ms │ 29 ms │ 81 ms │ 26.49 ms │ 14.54 ms │ 261 ms │
[1] └─────────┴───────┴───────┴───────┴───────┴──────────┴──────────┴────────┘
[1] ┌───────────┬─────────┬─────────┬─────────┬────────┬───────────┬────────┬─────────┐
[1] │ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%  │ Avg       │ Stdev  │ Min     │
[1] ├───────────┼─────────┼─────────┼─────────┼────────┼───────────┼────────┼─────────┤
[1] │ Req/Sec   │ 29 055  │ 29 055  │ 37 407  │ 37 631 │ 37 050,94 │ 1512,6 │ 29 044  │
[1] ├───────────┼─────────┼─────────┼─────────┼────────┼───────────┼────────┼─────────┤
[1] │ Bytes/Sec │ 13.9 MB │ 13.9 MB │ 17.9 MB │ 18 MB  │ 17.7 MB   │ 723 kB │ 13.9 MB │
[1] └───────────┴─────────┴─────────┴─────────┴────────┴───────────┴────────┴─────────┘
[1]
[1] Req/Bytes counts sampled once per second.
[1] # of samples: 30
[1]
[1] 1112k requests in 30.05s, 531 MB read

lib/request.js Outdated Show resolved Hide resolved
lib/request.js Outdated Show resolved Hide resolved
Co-authored-by: Gürgün Dayıoğlu <hey@gurgun.day>
Signed-off-by: Susan <25956407+dmkng@users.noreply.github.com>
Copy link
Member

@gurgunday gurgunday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Signed-off-by: Susan <25956407+dmkng@users.noreply.github.com>
Comment on lines 116 to 121
ip: {
get () {
return proxyAddr(this.raw, proxyFn)
const addrs = proxyAddr.all(this.raw, proxyFn)
return addrs[addrs.length - 1]
}
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just leaving a note here that this won't slow down the performance if only one IP exists, as proxyAddr itself also calls proxyAddr.all, and returns the last element of the returned array, so it does the same thing

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollina mcollina merged commit 8cc2045 into fastify:main May 15, 2024
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants