-
-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Performance: Prevents the zap logger from serializing the request in rewrite.go. #6541
Performance: Prevents the zap logger from serializing the request in rewrite.go. #6541
Conversation
1ae5db0
to
d206976
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
The work happens even if nothing ends up being logged.
That surprises me. I thought zap was optimized to only encode and write what is actually being logged.
Zap does have a WithLazy, but it will not immediately capture the request and instead keep a reference to it for later. Which means the request might be mutated at the moment of actually capturing it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM now. Thanks for the improvement!
You mentioned we can get a 10% speedup in the HTTP server as well. I'm not sure it's acceptable to use the Lazy approach since we need to log the original request before it goes through handling... is there another way?
(Also, I'm kind of surprised this is so inefficient. Are we not using the zero-allocation methods?)
The only other option I can think of would be to clone the request via
(Take these benchmarks with a grain of salt, Docker Ubuntu WSL Intel i9) |
Our loggable HTTP request allocates a bit I think. |
According to the flame graphs half of it comes from cloning the logger and the other half from json encoding the request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha. Thanks for this improvement!
Consider a Caddy config looking like this:
When looking at the performance profile of Caddy I noticed that a lot of time is being spent setting the context of the logger. In the following flamegraph (captured with brendangregg/FlameGraph) you can see that for the simple 'Hello Caddy' request above roughly 10% of time is being spent serializing the request for the
zap
logger using.With(..)
.Half of it is being spent on serializing the request for the error logger here:
caddy/modules/caddyhttp/server.go
Lines 311 to 316 in 2028da4
The other half is being spent on serializing the request for the Debug logger here:
https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/rewrite/rewrite.go#L135-L137
The work happens even if nothing ends up being logged.
This PR attempts fixing the second case, making the complete request with
rewrite
about 5% faster when debug logging is not enabled. (with a quick local wrk benchmark I'm going from ~1.350.000 requests/minute to 1.500.000 requests/minute)I don't know if there's a workaround for the first case since the Error logger in
server.go
seems to need the initial request data.