Skip to content

avoid heap allocs in transform.Inspect and transform.InspectExpr#3348

Merged
jycor merged 8 commits intomainfrom
james/transform
Dec 17, 2025
Merged

avoid heap allocs in transform.Inspect and transform.InspectExpr#3348
jycor merged 8 commits intomainfrom
james/transform

Conversation

@jycor
Copy link
Copy Markdown
Contributor

@jycor jycor commented Dec 16, 2025

Changes:

  • transform.Inspect switches on UnaryNode and BinaryNode to avoid heap allocations from node.Children()
  • transform.InspectExpr switches on UnaryExpression and BinaryExpression to avoid heap allocations from expression.Children()
  • remove UnaryExpression implementation from unaryAggBase and some functions that can return multiple children.

Benchmarks: dolthub/dolt#10222 (comment)

Copy link
Copy Markdown
Member

@zachmu zachmu left a comment

Choose a reason for hiding this comment

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

LGTM

Another thing to think about: we very frequently want to iterate over Children and it doesn't matter that they're a slice for this use case. We could change the signature of Children to be a seq.Iter and avoid all the allocs in these cases. Could probably use cursor to do most of this.

return false
})
if stop {
return false
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Isn't this backwards? Don't you want to stop as soon as you find a foundMatchAgainst expr?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This does stop once foundMatchAgainst expr is found. The logic is backwards for transform.Inspect vs transform.InspectExpr. I was initially going to swap the logic in this PR, but the changes quickly got unwieldy, so I left the TODOs for now.

// InspectExpr performs a post-order traversal of the sql.Expression tree;
// First, `f` is called on `expr.Children()` and if stop = false, then InspectExpr is recursively called on node's
// children.
// TODO: this conflicts with transform.Inspect which performs a pre-order traversal and stops when cont = false.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is actually really annoying. All the callback boolean returns in this package should mean the same thing, either continue or stop. Continue is probably better to standardize on.

@jycor jycor merged commit 60f4b0a into main Dec 17, 2025
7 of 8 checks passed
@jycor jycor deleted the james/transform branch December 17, 2025 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants