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

reuse ValuerEval objects #10414

Merged
merged 1 commit into from
Feb 6, 2019
Merged

Conversation

seebs
Copy link
Contributor

@seebs seebs commented Oct 25, 2018

Scanner objects and iterators often need a ValuerEval. This
object is created, often with a function call, and has at
least one interface in it, so it allocates storage. Then it's
dropped again right away. The only part of it that might be
subject to change is usually a map. While the map's contents
change over time, the actual map doesn't change for the
lifetime of the object.

So, in both iterators and scanners, stash the ValuerEval
and continue reusing it. On a query returning a fair number
of data points, this produces a small (<5% in practice)
improvement in observed performance, visible as a significant
reduction in time spent in runtime (mallocgc, newobject,
etcetera).

The performance improvement isn't big, but it's reasonably
easy to evaluate it and establish that it's a safe change
to make.

Signed-off-by: seebs seebs@seebs.net

Required for all non-trivial PRs
  • Sign CLA (if not already signed)
Required only if applicable

You can erase any checkboxes below this note if they are not applicable to your Pull Request.
[none apply]

Notes:

  • I didn't create an issue for this, but it's a side-effect of getting curious about query-response performance and wanting to do science.
  • This is mostly a thing I'm messing with in order to learn my way around the code because I had thoughts about possibly trying to reduce the number of interface{} being slung around.
  • The performance difference is pretty small, but it is more noticeable if you use msgpack. Still pretty small.

@jsternberg
Copy link
Contributor

At first glance it seems good. We're doing a release very soon though so I'm going to circle back to this later and double check if it's ok to merge.

@seebs
Copy link
Contributor Author

seebs commented Nov 5, 2018

Seems reasonable. In terms of actual memory allocation load, it's basically gonna be invisible compared to the interfaces anyway. :P

@mark-rushakoff mark-rushakoff changed the base branch from master to 1.8 January 11, 2019 19:00
@e-dard
Copy link
Contributor

e-dard commented Feb 1, 2019

@seebs we will look at this for the next release. Can you remove your changes to the CHANGELOG? We handle editing that. @jsternberg can you make a review if you get time?

@e-dard e-dard requested a review from jsternberg February 1, 2019 16:16
@e-dard e-dard added the community-pr Pull requests from the community. Thank you! label Feb 1, 2019
@e-dard e-dard added this to the 1.8 milestone Feb 1, 2019
@seebs seebs force-pushed the seebs/valuerReuse branch from 8847bab to 64ed3a9 Compare February 3, 2019 18:02
@seebs
Copy link
Contributor Author

seebs commented Feb 3, 2019

Updated with the changelog thing dropped. This doesn't apply to master, I think because of code reorganization, but I haven't looked very closely.

@jsternberg
Copy link
Contributor

I'll take care of rebasing it if needed. Thanks for the help.

I'll be looking at this tomorrow so it will likely be merged then.

@seebs
Copy link
Contributor Author

seebs commented Feb 3, 2019

Thanks! I'm not convinced it's fully thought-through; there might be a much better design lurking. This was mostly picked as a low-impact way to drop a ton of alloc/gc load without substantially changing anything.

@@ -223,6 +224,17 @@ func newFloatIterator(name string, tags query.Tags, opt query.IteratorOptions, c
itr.conds.names = condNames
itr.conds.curs = conds

// note: if opt.Condition is nil, itr.m can be nil.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove this comment. Passing nil to the MapValuer should be fine regardless. Assigning to it would cause a panic, but that's not relevant to the valuer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, that hadn't occurred to me.

Copy link
Contributor

@jsternberg jsternberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Remove the one comment I noted was unnecessary and I'll merge this. If @e-dard gets to it before me, he can also merge it.

Scanner objects and iterators often need a ValuerEval. This
object is created, often with a function call, and has at
least one interface in it, so it allocates storage. Then it's
dropped again right away. The only part of it that might be
subject to change is usually a map. While the map's contents
change over time, the actual map doesn't change for the
lifetime of the object.

So, in both iterators and scanners, stash the ValuerEval
and continue reusing it. On a query returning a fair number
of data points, this produces a small (<5% in practice)
improvement in observed performance, visible as a significant
reduction in time spent in runtime (mallocgc, newobject,
etcetera).

The performance improvement isn't big, but it's reasonably
easy to evaluate it and establish that it's a safe change
to make.

Signed-off-by: seebs <seebs@seebs.net>
@seebs seebs force-pushed the seebs/valuerReuse branch from 64ed3a9 to 5525240 Compare February 5, 2019 21:10
@jsternberg jsternberg merged commit 2811cde into influxdata:1.8 Feb 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community-pr Pull requests from the community. Thank you! kind/feature-request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants