-
Notifications
You must be signed in to change notification settings - Fork 107
Run plan.Clean() upon error too + refactor pointslicepool #1858
Conversation
4d3c106
to
206cced
Compare
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.
Generally looks good, couple comments.
FYI, we recently disabled plan.Clean()
due to some (very rare) corruption in responses we were seeing. Still waiting to see if disabling plan.Clean()
fixes it. If it does, we'll need to do another round to figure out what is going on.
@@ -36,7 +35,7 @@ func (s *FuncAbsolute) Exec(dataMap DataMap) ([]models.Series, error) { | |||
serie.Target = fmt.Sprintf("absolute(%s)", serie.Target) | |||
serie.Tags = serie.CopyTagsWith("absolute", "1") | |||
serie.QueryPatt = fmt.Sprintf("absolute(%s)", serie.QueryPatt) | |||
out := pointSlicePool.Get().([]schema.Point) | |||
out := pointSlicePool.Get() |
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.
A lot of functions know how many datapoints they need and could use GetMin
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.
true, but i don't have time now to go over all those
pointslicepool/pointslicepool.go
Outdated
return &PointSlicePool{ | ||
defaultSize: defaultSize, | ||
p: sync.Pool{ | ||
New: func() interface{} { |
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'm wondering if we want to allocate a default slice here or just let it return nil. If someone calls GetMin(2001)
and we didn't have anything in the pool, we will allocate two slices (capacities 2000 and 2001).
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.
If we return nil, then we put quite some burden on callers that call Get rather than GetMin. If those callers want to be efficient, they have to mind their own allocations, which defeats the point.
I suggest that if or when we do the work to transition call sites to GetMin, we can then apply your suggestion. Or even better, remove the Get method alltogether and make the hint mandatory.
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 think you misunderstood. Basically, no callers should ever access PointSlicePool.p
directly. This means PointSlicePool.Get()
is free to just be an alias for GetMin(100)
(or whatever) and GetMin
has the logic to allocate if nil
is returned.
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.
Basically, no callers should ever access PointSlicePool.p directly
sure. to be clear, this is already the case. (.p
is a private property so nothing in a different package can access it)
This means PointSlicePool.Get() is free to just be an alias for GetMin(100) (or whatever) and GetMin has the logic to allocate if nil is returned.
Seems like the choice of the number 100 here is the same as the choice of DefaultPointSliceSize, so we may as well use DefaultPointSliceSize here.
so doing what we have ....
New: func() interface{} {
return make([]schema.Point, 0, defaultSize)
},
seems equivalent to calling GetMin(DefaultPointSliceSize)
, GetMin receiving a nil and then allocating a slice of the requested size.
(sorry i guess i'm still not getting what you're saying)
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.
seems equivalent to calling GetMin(DefaultPointSliceSize), GetMin receiving a nil and then allocating a slice of the requested size.
For the raw Get
case, yes it is the same. But for GetMin(N)
where N > DefaultPointSliceSize
we save an allocation of DefaultPointSliceSize
. For example, GetMin(2001)
with an empty pool will currently allocate a cap(2000)
slice, put it right back into the pool because it's too small and then allocate cap(2001)
slice.
With the suggested implementation GetMin(2001)
will get nil
from the pool and will allocate the cap(2001)
slice. No extra cap(2000)
slice allocated.
So, under the assumption that at some point we can update the Get
calls (almost) everywhere to use GetMin
(which honestly should be very easy because in most funcs it's just len(serie.Datapoints)
) then we should see the benefit of this approach.
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.
ok, now i see what you're saying.
how does 3754a85 look ?
one side-effect of this is that in theory regular calls to Get(), which previously would get a small (big enough to be useful, but smaller than p.defaultSize) slice, now would return that slice, and allocate a bigger one instead.
But in practice i don't see that happening because slices being added to the pool should all have come from either Get() or GetMin() anyway
while we're at it, add some syntactic sugar
206cced
to
c2cc3fb
Compare
rebased on latest master. |
is there an update on this? this is probably resolved as of the recent related fixes wrt the double put etc I think? |
We haven't actually gotten a chance to rollout the latest fix. The last update I have is that we do conditional |
No description provided.