db: remove Iterator.SetBounds optimization for unchanging bounds#1073
db: remove Iterator.SetBounds optimization for unchanging bounds#1073sumeerbhola merged 1 commit intocockroachdb:masterfrom
Conversation
Also clarify the semantics on when bounds slices can be mutated by the caller. This optimization was the cause of the failures in CockroachDB's cdc/bank/cluster-recovery test. There is no new test here since the contract is now on the caller's side (there will be a CockroachDB test to ensure that the contract is not being violated).
petermattis
left a comment
There was a problem hiding this comment.
Reviewable status: 0 of 2 files reviewed, 1 unresolved discussion (waiting on @itsbilal, @jbowens, and @sumeerbhola)
iterator.go, line 862 at r1 (raw file):
((upper != nil) != (i.opts.UpperBound != nil)) if !lowerOrUpperDifferentNils && bytes.Equal(lower, i.opts.LowerBound) && bytes.Equal(upper, i.opts.UpperBound) {
I'm curious what the flaw in this optimization was. I'm still not seeing the flaw in looking at it right now.
This is to compensate for the bug fix in Pebble which removes the noop behavior from Pebble cockroachdb/pebble#1073 Added a test that checks that the noop behavior is working, the contract regarding slice stability is followed, and that the bounds are correct. Additionally, there are some minor tweaks involving removal and addition of some defensive code. The additions are related to the pebbleIterator.reusable field. Release justification: Fix for high-severity bug in existing functionality. The Pebble bug fix that needs to be compensated here could lead to incorrect results from iterators, even prior to the latest seek optimization in Pebble (though our existing tests were not failing prior to that latest seek optimization). Release note: None
sumeerbhola
left a comment
There was a problem hiding this comment.
Reviewable status: 0 of 2 files reviewed, 1 unresolved discussion (waiting on @itsbilal, @jbowens, and @petermattis)
iterator.go, line 862 at r1 (raw file):
Previously, petermattis (Peter Mattis) wrote…
I'm curious what the flaw in this optimization was. I'm still not seeing the flaw in looking at it right now.
It's the case specified in the new code comment starting with "Note that the callee cannot itself look ..."
In pebbleIterator we reuse slices when setting bounds by rotating through 2 slices for each bound e.g. slice 0 for current lower bound is left untouched when the lower bound changes and instead slice 1 is populated and passed in SetBounds.
This could have tripped up the existing seek optimizations too, but for some reason only came to light when I added the latest noop seek optimization.
The corresponding noop optimization for CockroachDB is in cockroachdb/cockroach#61194
petermattis
left a comment
There was a problem hiding this comment.
Will this need to be backported to 20.2? I can't recall if this optimization was present there.
Reviewable status: 0 of 2 files reviewed, 1 unresolved discussion (waiting on @itsbilal, @jbowens, and @sumeerbhola)
iterator.go, line 862 at r1 (raw file):
Previously, sumeerbhola wrote…
It's the case specified in the new code comment starting with "Note that the callee cannot itself look ..."
InpebbleIteratorwe reuse slices when setting bounds by rotating through 2 slices for each bound e.g. slice 0 for current lower bound is left untouched when the lower bound changes and instead slice 1 is populated and passed in SetBounds.
This could have tripped up the existing seek optimizations too, but for some reason only came to light when I added the latest noop seek optimization.
The corresponding noop optimization for CockroachDB is in cockroachdb/cockroach#61194
Ah, got it. Thanks.
sumeerbhola
left a comment
There was a problem hiding this comment.
TFTR!
Will this need to be backported to 20.2? I can't recall if this optimization was present there.
No, this was added after 20.2
Reviewable status: 0 of 2 files reviewed, 1 unresolved discussion (waiting on @itsbilal, @jbowens, and @sumeerbhola)
This is to compensate for the bug fix in Pebble which removes the noop behavior from Pebble cockroachdb/pebble#1073 Added a test that checks that the noop behavior is working, the contract regarding slice stability is followed, and that the bounds are correct. Additionally, there are some minor tweaks involving removal and addition of some defensive code. The additions are related to the pebbleIterator.reusable field. Release justification: Fix for high-severity bug in existing functionality. The Pebble bug fix that needs to be compensated here could lead to incorrect results from iterators, even prior to the latest seek optimization in Pebble (though our existing tests were not failing prior to that latest seek optimization). Release note: None
60854: cli: enhance the `cockroach connect` command r=aaron-crl,itsbilal a=knz Puts pieces together for #60632. See individual commits for details. Release justification: low risk, high benefit changes to existing functionality 61029: bazel: generate `//go:generate sh generate.sh` within Bazel r=rickystewart a=alan-mas Part of #57787 work. As gazelle is not taking care by itself in any changes related to //go:generate ... (anything that has a go run as a prefix) we are creating a genrule and we need to handle every each of them separately. We are creating a genrule based on pkg/geo/wkt/generate.sh to avoid change that script as it seems it is only used to "change" a flag (has a TODO task inside it). Release note: None Release justification: non-production code change 61194: storage: add noop behavior for bounds setting in pebbleIterator r=sumeerbhola a=sumeerbhola This is to compensate for the bug fix in Pebble which removes the noop behavior from Pebble cockroachdb/pebble#1073 Added a test that checks that the noop behavior is working, the contract regarding slice stability is followed, and that the bounds are correct. Additionally, there are some minor tweaks involving removal and addition of some defensive code. The additions are related to the pebbleIterator.reusable field. Release justification: Fix for high-severity bug in existing functionality. The Pebble bug fix that needs to be compensated here could lead to incorrect results from iterators, even prior to the latest seek optimization in Pebble (though our existing tests were not failing prior to that latest seek optimization). Release note: None 61240: vendor: upgrade go-geom to pickup more GEOMETRYCOLLECTION EMPTY fixes r=andyyang890 a=otan This allows us to further differentiate GEOMETRYCOLLECTION EMPTY from GEOMETRYCOLLECTION Z/ZM/M EMPTY. Release justification: low risk change to new functionality Release note: None Co-authored-by: Raphael 'kena' Poss <knz@thaumogen.net> Co-authored-by: Alanmas <acostas.alan@gmail.com> Co-authored-by: sumeerbhola <sumeer@cockroachlabs.com> Co-authored-by: Oliver Tan <otan@cockroachlabs.com>
Restore the SetBounds optimization that avoids invalidating the iterator during a call to SetBounds if the bounds are unchanged. This optimization was removed in cockroachdb#1073 because the previous version of this optimization improperly retained the old bounds which might be mutated by the user. In this reintroduction of the optimization, a call to SetBounds with unchanged bounds still propagates the new bounds down the entire iterator tree. However, if the bounds are equal, the iterator state is not invalidated, allowing subsequent seeks to take advantage of optimizations like try-seek-using-next. Additionally, apply the same optimization to SetOptions.
Restore the SetBounds optimization that avoids invalidating the iterator during a call to SetBounds if the bounds are unchanged. This optimization was removed in cockroachdb#1073 because the previous version of this optimization improperly retained the old bounds which might be mutated by the user. In this reintroduction of the optimization, a call to SetBounds with unchanged bounds still propagates the new bounds down the entire iterator tree. However, if the bounds are equal, the iterator state is not invalidated, allowing subsequent seeks to take advantage of optimizations like try-seek-using-next. Additionally, apply the same optimization to SetOptions.
Restore the SetBounds optimization that avoids invalidating the iterator during a call to SetBounds if the bounds are unchanged. This optimization was removed in cockroachdb#1073 because the previous version of this optimization improperly retained the old bounds which might be mutated by the user. In this reintroduction of the optimization, a call to SetBounds with unchanged bounds still propagates the new bounds down the entire iterator tree. However, if the bounds are equal, the iterator state is not invalidated, allowing subsequent seeks to take advantage of optimizations like try-seek-using-next. Additionally, apply the same optimization to SetOptions.
Restore the SetBounds optimization that avoids invalidating the iterator during a call to SetBounds if the bounds are unchanged. This optimization was removed in cockroachdb#1073 because the previous version of this optimization improperly retained the old bounds which might be mutated by the user. In this reintroduction of the optimization, a call to SetBounds with unchanged bounds still propagates the new bounds down the entire iterator tree. However, if the bounds are equal, the iterator state is not invalidated, allowing subsequent seeks to take advantage of optimizations like try-seek-using-next. Additionally, apply the same optimization to SetOptions.
Restore the SetBounds optimization that avoids invalidating the iterator during a call to SetBounds if the bounds are unchanged. This optimization was removed in cockroachdb#1073 because the previous version of this optimization improperly retained the old bounds which might be mutated by the user. In this reintroduction of the optimization, a call to SetBounds with unchanged bounds still propagates the new bounds down the entire iterator tree. However, if the bounds are equal, the iterator state is not invalidated, allowing subsequent seeks to take advantage of optimizations like try-seek-using-next. Additionally, apply the same optimization to SetOptions.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in cockroachdb#1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes cockroachdb#1667.
Restore the SetBounds optimization that avoids invalidating the iterator during a call to SetBounds if the bounds are unchanged. This optimization was removed in cockroachdb#1073 because the previous version of this optimization improperly retained the old bounds which might be mutated by the user. In this reintroduction of the optimization, a call to SetBounds with unchanged bounds still propagates the new bounds down the entire iterator tree. However, if the bounds are equal, the iterator state is not invalidated, allowing subsequent seeks to take advantage of optimizations like try-seek-using-next. Additionally, apply the same optimization to SetOptions.
Restore the SetBounds optimization that avoids invalidating the iterator during a call to SetBounds if the bounds are unchanged. This optimization was removed in cockroachdb#1073 because the previous version of this optimization improperly retained the old bounds which might be mutated by the user. In this reintroduction of the optimization, a call to SetBounds with unchanged bounds still propagates the new bounds down the entire iterator tree. However, if the bounds are equal, the iterator state is not invalidated, allowing subsequent seeks to take advantage of optimizations like try-seek-using-next. Additionally, apply the same optimization to SetOptions.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in cockroachdb#1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes cockroachdb#1667.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in cockroachdb#1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes cockroachdb#1667.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in cockroachdb#1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes cockroachdb#1667.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in cockroachdb#1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes cockroachdb#1667.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in cockroachdb#1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes cockroachdb#1667.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in cockroachdb#1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes cockroachdb#1667.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in cockroachdb#1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes cockroachdb#1667.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in cockroachdb#1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes cockroachdb#1667.
When a new iterator is constructed or when an existing iterator's bounds are modified, copy the bounds into a Pebble-allocated slice. This gives Pebble control over the lifetime of the bound buffers and allows Pebble to restore the optimization for unchanged bounds that was removed in #1073. Two buffers are used, one for the current bounds and one for old bounds. This scheme allows low-level internal iterators in Pebble to compare new and old bounds so that context-dependent optimizations may be applied. These bounds buffers are pooled on the iterAlloc to reduce allocations. These new semantics are simpler and allow Pebble's SetOptions to perform more optimizations. They come at the cost of the additional key copies, regardless of whether the Iterator's bounds will change. Supersedes #1667.
Also clarify the semantics on when bounds slices can be mutated
by the caller.
This optimization was the cause of the failures in CockroachDB's
cdc/bank/cluster-recovery test. There is no new test here since
the contract is now on the caller's side (there will be a
CockroachDB test to ensure that the contract is not being
violated).