Skip to content

Commit

Permalink
distsql: reduce allocations in setupFlow
Browse files Browse the repository at this point in the history
Previously, the variable `evalCtx *eval.Context` escaped to the
heap because it was captured by an `onFlowCleanupEnd` closure in one
branch of a conditional and modified in another branch. Go's escape
analysis cannot determine that the capture and modification are mutually
exclusive, so the pointer is heap allocated. This commit eliminates the
allocation by using a new `*eval.Context` variable in the closure that
is never modified.

Release note: None
  • Loading branch information
mgartner committed Dec 16, 2024
1 parent cc88696 commit 3f31914
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions pkg/sql/distsql/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,13 +269,20 @@ func (ds *ServerImpl) setupFlow(
// this allows us to avoid an unnecessary deserialization of the eval
// context proto.
evalCtx = localState.EvalContext
// We create an eval context variable scoped to this block and reference
// it in the onFlowCleanupEnd closure. If the closure referenced
// evalCtx, then the pointer would be heap allocated because it is
// modified in the other branch of the conditional, and Go's escape
// analysis cannot determine that the capture and modification are
// mutually exclusive.
localEvalCtx := evalCtx
// We're about to mutate the evalCtx and we want to restore its original
// state once the flow cleans up. Note that we could have made a copy of
// the whole evalContext, but that isn't free, so we choose to restore
// the original state in order to avoid performance regressions.
origTxn := evalCtx.Txn
origTxn := localEvalCtx.Txn
onFlowCleanupEnd = func() {
evalCtx.Txn = origTxn
localEvalCtx.Txn = origTxn
reserved.Close(ctx)
}
if localState.MustUseLeafTxn() {
Expand All @@ -286,7 +293,7 @@ func (ds *ServerImpl) setupFlow(
}
// Update the Txn field early (before f.SetTxn() below) since some
// processors capture the field in their constructor (see #41992).
evalCtx.Txn = leafTxn
localEvalCtx.Txn = leafTxn
}
} else {
onFlowCleanupEnd = func() {
Expand Down

0 comments on commit 3f31914

Please sign in to comment.