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

Improve lexer performance by using a byte array as source #137

Merged
merged 1 commit into from
Jun 12, 2016

Conversation

Matthias247
Copy link

I did some peformance testing for graphql-go and found out that it was superslow for my use-case (about 300ms for processing a simple query). After using the go profiling tools it was obvious that the Garbage Collector takes most of the time for it (> 250ms).

I have then viewed through the graphql related code and have seen that the Lexer produces an extreme amount of garbage. The reason is that the Lexer stores the request as a string type but converts it to ´[]rune` every time it wants to read a char. This will cause an allocation and copy for reading each character!

I have now made changes were the Source is directly storing a []byte array, which can be indexed without performance penalty and which is never converted to a rune array. I changed some functions to read runes from the given offset and the source array and to be able to skip over them even if they are multibyte values.

This pull request improves performance for me by factor 30! This means I'm coming to 10ms for processing a request, which is still not stellar but more workable. In the new performance traces the lexer is no longer the most time consuming part.

The code was not heavily reviewed, so I suggest someone else also takes a look at it before merging. But tests are working and my application with it is working too.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 90.751% when pulling be39d41 on Matthias247:lexperf into a5cf5f2 on graphql-go:master.

@sogko
Copy link
Member

sogko commented Jun 11, 2016

Hi @Matthias247

Thanks for taking your time to dive deep into this and submitting a PR, appreciate it very much 👍

Briefly glancing through the changes, it looks good. I'll take the time to review it ASAP.

Cheers!

@coveralls
Copy link

Coverage Status

Coverage remained the same at 90.754% when pulling d060075 on Matthias247:lexperf into 500a3ff on graphql-go:master.

@sogko sogko merged commit 065ab6b into graphql-go:master Jun 12, 2016
sogko added a commit to sogko/graphql that referenced this pull request Jun 12, 2016
…h commit graphql-go#137

- Increased coverage for `lexer` package to 100%
- Added more tests to cover parsing unicode strings (graphql-go#135) as well.
- Fixed invalid test for `lexer` properly escaping slashes for TokenString type
sogko added a commit that referenced this pull request Jun 12, 2016
sogko added a commit to sogko/graphql that referenced this pull request Jan 27, 2017
* master:
  gofmt -s
  executor: add graphql tag
  Fix ObjectConfig duplicate json tag. Name had a 'description' json tag which was duplicate
  Minor fix to stop `go vet` from complaining
  Add 1.7 and tip to build matrix for Go
  Minor fix to stop `go vet` from complaining
  README: add Documentation section
  Fixes tests that was broken with enhancements made to the `lexer` with commit graphql-go#137
  Improve lexer performance by using a byte array as source
  Updated `graphql.Float` coercion - if value type is explicitly `float32`, return `float32` - if value type is explicitly `float64`, return `float64` - if value type is `string`, return `float64` - for everything else, use system-default
sogko added a commit to sogko/graphql that referenced this pull request Jan 27, 2017
* sogko/0.6.0: (34 commits)
  gofmt -s
  executor: add graphql tag
  Fix ObjectConfig duplicate json tag. Name had a 'description' json tag which was duplicate
  Minor fix to stop `go vet` from complaining
  Add 1.7 and tip to build matrix for Go
  Minor fix to stop `go vet` from complaining
  README: add Documentation section
  Fixes tests that was broken with enhancements made to the `lexer` with commit graphql-go#137
  Improve lexer performance by using a byte array as source
  Validation: improving overlapping fields quality (graphql-go#386)
  Validation: context.getFragmentSpreads now accepts selectionSet rather than fragment AST node
  Factor out more closure functions
  Factor out closure functions to normal functions
  Deprecated directive (graphql-go#384)
  Revert back directives to use `var`; `const` not applicable here
  Deprecated directive (graphql-go#384)
  RFC: Directive location: schema definition (graphql-go#382)
  RFC: Schema Language Directives (graphql-go#376)
  Update `NewSchema()` to use new exported introspective types
  Export introspection in public API
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants