- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.7k
feat(inputs.statsd): Improve performance #17872
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
Conversation
| Thanks so much for the pull request! | 
| !signed-cla | 
        
          
                plugins/inputs/statsd/statsd_test.go
              
                Outdated
          
        
      | err := parser.Init() | ||
| require.NoError(b, err) | 
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.
Same for all other occurrences
| err := parser.Init() | |
| require.NoError(b, err) | |
| require.NoError(b, parser.Init()) | 
        
          
                plugins/inputs/statsd/statsd.go
              
                Outdated
          
        
      | p := &graphite.Parser{Separator: s.MetricSeparator, Templates: s.Templates} | ||
| err := p.Init() | ||
| if err != nil { | ||
| return err | ||
| } | 
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.
Maybe extract in a new func which returns *graphite.Parser, error?
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.
I created it and used it also in tests
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.
Perfect, that was the idea.
        
          
                plugins/inputs/statsd/statsd.go
              
                Outdated
          
        
      |  | ||
| // newGraphiteParser initializes and returns a new graphite.Parser. graphite.Parser returned is not safe to be used in | ||
| // multiple goroutines. | ||
| func newGraphiteParser(s *Statsd) (*graphite.Parser, error) { | 
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.
What about this?
| func newGraphiteParser(s *Statsd) (*graphite.Parser, error) { | |
| func (s *Statsd) newGraphiteParser() (*graphite.Parser, error) { | 
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.
done
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.
@Hipska one of the pipelines failed but I think it's not related to the changes
| Download PR build artifacts for linux_amd64.tar.gz, darwin_arm64.tar.gz, and windows_amd64.zip. 📦 Click here to get additional PR build artifactsArtifact URLs | 
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 your contribution @radykal-com!
I think your code is racy for the case where another message is coming in via s.in in the parser function while we are currently using the parser. More specifically when setting p.DefaultTags in parseName().
If a second call (for another s.in message) arrives at that line before (or even worse while) the first call is executing the templates you will get mangled tags in your template result. We had this issue before and therefore introduced the lock.
What you could do though is to use a sync.Pool or parsers to be able to handle multiple messages in parallel while reusing the parser!
| 
 That cannot happen because each  I'm pretty sure its working because the code is running in our high traffic metrics aggregator for the past week and is working fine (no panic) and the tests just pass OK with the  | 
| @Hipska any chance to rerun the pipeline to get the failing one pass? | 
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 your explanation @radykal-com! I agree with your assessment.
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.
@radykal-com Nice work! Thanks for the contribution!
Summary
Avoid using the mutex in each metric name parse by passing each worker goroutine its own
graphite.Parser.Checklist
Related issues
resolves #12313
Benchmark
There is a big difference in the overall throughput when using multiple threads
Old code
New code