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

Performance improvments #465

Merged
merged 3 commits into from
Dec 10, 2018
Merged

Performance improvments #465

merged 3 commits into from
Dec 10, 2018

Conversation

vektah
Copy link
Collaborator

@vektah vektah commented Dec 8, 2018

Added a benchmark for a simple query and make a 2 quick optimisations:

  • don't use strconv.Quote when writing object keys to save a bunch of allocs
  • execute the first concurrent field on the request goroutine, instead always creating a new goroutine.

before

    go test -benchtime=5s -bench=. -benchmem
    goos: linux
    goarch: amd64
    pkg: github.com/99designs/gqlgen/example/starwars
    BenchmarkSimpleQueryNoArgs-8      200000             32680 ns/op            6357 B/op        126 allocs/op
    PASS
    ok      github.com/99designs/gqlgen/example/starwars    9.901s

image

You can see morestack dominating the graph here (28%). This happens because we create new goroutines around every resolver, and even though go does recycle old goroutine in a pool, it doesn't maintain their stacks.

after

    go test -benchtime=5s -bench=. -benchmem    
    goos: linux
    goarch: amd64
    pkg: github.com/99designs/gqlgen/example/starwars
    BenchmarkSimpleQueryNoArgs-8      300000             25093 ns/op            6453 B/op        114 allocs/op
    PASS
    ok      github.com/99designs/gqlgen/example/starwars    10.807s

image

~ 30% faster.

Ideas for future tweaks:

  • 15% is still spent on morestack + 13% in starwars.ec_Human_starship: Marshalling arrays in results also happens concurrently, theres another high fanout go func() in here. This causes lots of short lived goroutines, which allocate more stack. Probably the next target.
  • 8% in json.Marshal: This can be replaced with our internal json writer, avoiding all of the reflection and many allocations. Needs a little bit of thought around encoding extensions, do we fall back to json.Marshal?
  • 7% in json.Decode: Maybe there is a faster json decoder out there for this?

go test -benchtime=5s -bench=. -benchmem
goos: linux
goarch: amd64
pkg: github.com/99designs/gqlgen/example/starwars
BenchmarkSimpleQueryNoArgs-8      200000             32680 ns/op            6357 B/op        126 allocs/op
PASS
ok      github.com/99designs/gqlgen/example/starwars    9.901s
go test -benchtime=5s -bench=. -benchmem
goos: linux
goarch: amd64
pkg: github.com/99designs/gqlgen/example/starwars
BenchmarkSimpleQueryNoArgs-8      200000             32125 ns/op            6277 B/op        118 allocs/op
PASS
ok      github.com/99designs/gqlgen/example/starwars    9.768s
goos: linux
goarch: amd64
pkg: github.com/99designs/gqlgen/example/starwars
BenchmarkSimpleQueryNoArgs-8      300000             25093 ns/op            6453 B/op        114 allocs/op
PASS
ok      github.com/99designs/gqlgen/example/starwars    10.807s
@vektah vektah changed the base branch from master to next December 9, 2018 23:08
@vektah vektah merged commit 473f4f0 into next Dec 10, 2018
@vektah vektah deleted the performance-improvments branch December 10, 2018 22:59
@vektah vektah mentioned this pull request Mar 4, 2019
@vektah vektah mentioned this pull request Apr 17, 2019
3 tasks
@edsrzf edsrzf mentioned this pull request Aug 19, 2019
2 tasks
cgxxv pushed a commit to cgxxv/gqlgen that referenced this pull request Mar 25, 2022
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.

1 participant