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

Make the AST visitor faster #7701

Merged
merged 9 commits into from Mar 18, 2021
Merged

Make the AST visitor faster #7701

merged 9 commits into from Mar 18, 2021

Conversation

systay
Copy link
Collaborator

@systay systay commented Mar 16, 2021

Description

Walking the query tree, either all of it or parts of it, is something the the planner does a number of times. To make the actual traversal of the tree as efficient as possible is therefor something that would benefit many parts of Vitess.

That is what this PR sets out to do. The old sqlparser.Walk method was implemented using the Rewriter framework. That is not a perfect match, so we had to do a little work to fit them together.
This new implementation of the sqlparser.Walk functionality does three things differently, compared to the old on.

  1. It does explicit error checking for every step, instead of using panic/recover, like the Rewrite method does.
  2. Instead of doing everything in a single method, the new implementation has many smaller methods that handle each type. This allows for faster nil-checking where we don't have to use reflection for nil checking.
  3. Since the Walk visitor doesn't support replacing parts of the tree, we can use simpler code and not have to keep state to know which field needs to be replaced.

Together, this all leads to some nice improvements. Here are some microbenchmark results of just walking the AST:

name                      old time/op  new time/op  delta
WalkLargeExpression/0-16  1.36µs ± 3%  1.07µs ± 1%  -21.28%  (p=0.000 n=9+9)
WalkLargeExpression/1-16  5.44µs ± 1%  2.02µs ± 2%  -62.92%  (p=0.000 n=9+10)
WalkLargeExpression/2-16  1.44µs ± 3%  1.09µs ± 2%  -24.86%  (p=0.000 n=10+9)
WalkLargeExpression/3-16  10.3µs ± 2%   2.9µs ± 3%  -71.96%  (p=0.000 n=10+8)
WalkLargeExpression/4-16  11.0µs ± 3%   3.1µs ± 6%  -71.62%  (p=0.000 n=10+10)
WalkLargeExpression/5-16  1.36µs ± 1%  1.07µs ± 1%  -21.14%  (p=0.000 n=10+9)
WalkLargeExpression/6-16  11.1µs ± 3%   3.0µs ± 1%  -72.64%  (p=0.000 n=10+10)
WalkLargeExpression/7-16  6.83µs ± 1%  2.28µs ± 3%  -66.59%  (p=0.000 n=10+10)
WalkLargeExpression/8-16  12.0µs ± 2%   3.3µs ± 1%  -72.70%  (p=0.000 n=10+10)
WalkLargeExpression/9-16  1.42µs ± 3%  1.09µs ± 1%  -22.87%  (p=0.000 n=10+10)

On average, walking the these tree takes about half the time it used to.

If we instead benchmark the vtgate planbuilder, which is a heavy user of sqlparser.Walk, we get:

name                              old time/op    new time/op    delta
Planner/from_cases.txt-16            511µs ± 2%     444µs ± 2%  -13.18%  (p=0.008 n=5+5)
Planner/filter_cases.txt-16          409µs ± 3%     340µs ± 4%  -17.06%  (p=0.008 n=5+5)
Planner/large_cases.txt-16           117µs ± 1%     102µs ± 1%  -12.96%  (p=0.008 n=5+5)
Planner/aggr_cases.txt-16            119µs ± 4%     101µs ± 4%  -14.80%  (p=0.008 n=5+5)
Planner/select_cases.txt-16          724µs ± 1%     606µs ± 0%  -16.27%  (p=0.008 n=5+5)
Planner/union_cases.txt-16           814µs ± 2%     680µs ± 1%  -16.40%  (p=0.008 n=5+5)

name                              old alloc/op   new alloc/op   delta
Planner/from_cases.txt-16            239kB ± 0%     206kB ± 0%  -13.87%  (p=0.008 n=5+5)
Planner/filter_cases.txt-16          181kB ± 0%     145kB ± 0%  -19.93%  (p=0.008 n=5+5)
Planner/large_cases.txt-16          57.6kB ± 0%    50.2kB ± 0%  -12.82%  (p=0.008 n=5+5)
Planner/aggr_cases.txt-16           49.6kB ± 0%    40.0kB ± 0%  -19.38%  (p=0.008 n=5+5)
Planner/select_cases.txt-16          291kB ± 0%     237kB ± 0%  -18.38%  (p=0.008 n=5+5)
Planner/union_cases.txt-16           355kB ± 0%     287kB ± 0%  -19.12%  (p=0.008 n=5+5)

name                              old allocs/op  new allocs/op  delta
Planner/from_cases.txt-16            4.96k ± 0%     3.61k ± 0%  -27.14%  (p=0.008 n=5+5)
Planner/filter_cases.txt-16          4.22k ± 0%     2.76k ± 0%  -34.57%  (p=0.008 n=5+5)
Planner/large_cases.txt-16           1.22k ± 0%     0.92k ± 0%  -24.12%  (p=0.008 n=5+5)
Planner/aggr_cases.txt-16            1.26k ± 0%     0.87k ± 0%  -31.19%  (p=0.008 n=5+5)
Planner/select_cases.txt-16          7.08k ± 0%     4.87k ± 0%  -31.13%  (p=0.008 n=5+5)
Planner/union_cases.txt-16           8.88k ± 0%     6.01k ± 0%  -32.32%  (p=0.008 n=5+5)

Overall some nice improvements on both time and memory pressure.

Impacted Areas in Vitess

Components that this PR will affect:

  • Query Serving

Signed-off-by: Andres Taylor <andres@planetscale.com>
Signed-off-by: Andres Taylor <andres@planetscale.com>
Signed-off-by: Andres Taylor <andres@planetscale.com>
frouioui and others added 3 commits March 18, 2021 09:06
Signed-off-by: Florent Poinsard <florent.poinsard@outlook.fr>
Signed-off-by: Andres Taylor <andres@planetscale.com>
Signed-off-by: Andres Taylor <andres@planetscale.com>
@systay systay marked this pull request as ready for review March 18, 2021 10:41
@shlomi-noach
Copy link
Contributor

👋 any hints as for what this PR is expected to do? (no description in main comment)

@systay systay changed the title Visit() Make the AST visitor faster Mar 18, 2021
Copy link
Contributor

@shlomi-noach shlomi-noach left a comment

Choose a reason for hiding this comment

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

Parser optimizations are on 🔥

I'm not familiar with the code and the changes are hard for me to follow. But approving based on the detailed PR comment and based on successful tests. Advising to wait for review by someone with more insights.

Copy link
Member

@frouioui frouioui left a comment

Choose a reason for hiding this comment

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

So amazing 🔥

go/vt/sqlparser/old Outdated Show resolved Hide resolved
Copy link
Collaborator

@vmg vmg left a comment

Choose a reason for hiding this comment

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

very neat! clean up the checked in benchmark and let's merge this!

Signed-off-by: Andres Taylor <andres@planetscale.com>
@systay systay requested a review from vmg March 18, 2021 12:28
Signed-off-by: Andres Taylor <andres@planetscale.com>
return g.ptrToBasicMethod(t, ptrToType, gen)
})
default:
panic(fmt.Sprintf("%T", ptrToType))
Copy link
Member

Choose a reason for hiding this comment

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

nit: we can do log.fatal here, or is this intentional?

Copy link
Member

Choose a reason for hiding this comment

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

+1. If there's a good reason to panic, please document it.

Signed-off-by: Andres Taylor <andres@planetscale.com>
@systay systay merged commit 7297152 into vitessio:master Mar 18, 2021
@systay systay deleted the at-walk-gen branch March 18, 2021 16:23
@vmg vmg mentioned this pull request Mar 18, 2021
@askdba askdba added this to the v10.0 milestone Mar 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants