Smaller stack for set defaults#240
Closed
dominiquelefevre wants to merge 4 commits intogorilla:mainfrom
dominiquelefevre:smaller-stack-for-setDefaults
Closed
Smaller stack for set defaults#240dominiquelefevre wants to merge 4 commits intogorilla:mainfrom dominiquelefevre:smaller-stack-for-setDefaults
dominiquelefevre wants to merge 4 commits intogorilla:mainfrom
dominiquelefevre:smaller-stack-for-setDefaults
Conversation
Less nesting an a switch instead of if ... else if ... else if are easier to read.
…ts(). Using MultiError.merge() forces the caller to allocate an instance of MultiError just to add one error. Let us have a method add() that does this a temporary map. Also, add constants for errors that are copied- and-pasted. This may seem a minor performance improvement to skip an allocation, but in fact it is not. The go compiler detects that a temporary MultiError instance does not escape to the heap, and allocates it on the stack. Go 1.25 on amd64 would use 2408 bytes for the local variables of setDefaults(). This change reduces the local variables frame to 840 bytes. Large stack usage by setDefaults() is in fact very costly. Goroutines start with a small stack. A big frame for local variables makes it very probable that the go runtime will need to grow the stack upon a call to setDefaults(). In a service where I have observed this behaviour, Decoder.Decode() spends 3x more time in runtime.newstack() than in the rest of Decoder.Decode().
Inlining these calls gains nothing performance-wise, but uses a lot of stack. With these two calls de-inlined, setDefaults() uses 528 bytes for the local variables instead of 840.
Now setDefaults() needs 312 bytes for local variables instead of 528.
Author
|
Is anyone out here? @lll-lll-lll-lll? |
Contributor
|
Hi @dominiquelefevre, unfortunately the project have been abandoned by its maintainers. I talked to one of them few months ago, who said he's going to do something to move things, but until today, nothing can't be merged. With this being said, I am the person behind adding the default functionality to the project #183 , so I can take a look at this PR, and give you feedback, if you'd like. |
Author
|
@zak905, thank you for chiming in. Well, in this case I'd rather migrate my project off |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What type of PR is this? (check all applicable)
Description
Decoder.setDefaults()happens to use a lot of stack space for its local variables.Large stack usage by
setDefaults()is a performance problem because the go runtime assumes that goroutine stacks stay small. A big frame for local variables makes it very probable that the go runtime will need to grow the stack upon a call tosetDefaults(). In a service where I have observed this behaviour,Decoder.Decode()spends 3x more time inruntime.newstack()than in the rest ofDecoder.Decode().This patch set decreases the frame for
setDefaults()'s local variables from 2408 bytes to 312 (the figures are for go 1.25 on amd64).NOTE: the stack frame size of 2408 bytes guarantees that the goroutine stack will grow if
setDefaults()is called soon after a goroutine starts. Normally, there are some calls on the stack beforesetDefaults(), like the http server, the muxer, possibly otelhttp, etc. Because of thosesetDefaults()is only likely to grow the stack, not guaranteed to do so.Aside from reducing the stack usage, this patch series improves the speed of
go test -count=10000by some 4%.See individual commit messages for the rationale of each change.
Added/updated tests?
Run verifications and test
make verifyis passing:make verifyfails inmaindue togoseccomplaining about possible truncating conversions inconvertPointer(); this patch series adds no new failures.make testis passing