xitep opened a new pull request, #2271:
URL: https://github.com/apache/datafusion-sqlparser-rs/pull/2271

   * The whole change is just making `Expr::Function(Function)` a 
`Expr::Function(Box<Function>)` thereby reducing the size of `Expr` from 328 
down to 216 bytes.
   * This appears to be slightly improving the performance of the parser:
   <details>
   
   ```
   # on branch: `box-function`
   > cargo bench -- --baseline main
   ...
   sqlparser-rs parsing benchmark/sqlparser::select
                           time:   [2.7318 µs 2.7401 µs 2.7489 µs]
                           change: [−8.0290% −7.4339% −6.8525%] (p = 0.00 < 
0.05)
                           Performance has improved.
   Found 1 outliers among 100 measurements (1.00%)
     1 (1.00%) high mild
   sqlparser-rs parsing benchmark/sqlparser::with_select
                           time:   [14.875 µs 14.930 µs 14.995 µs]
                           change: [−5.0708% −4.3247% −3.5655%] (p = 0.00 < 
0.05)
                           Performance has improved.
   Found 3 outliers among 100 measurements (3.00%)
     3 (3.00%) high severe
   sqlparser-rs parsing benchmark/parse_large_statement
                           time:   [4.7099 ms 4.7206 ms 4.7313 ms]
                           change: [−9.8526% −9.3668% −8.8572%] (p = 0.00 < 
0.05)
                           Performance has improved.
   sqlparser-rs parsing benchmark/format_large_statement
                           time:   [268.01 µs 268.67 µs 269.37 µs]
                           change: [−1.2684% −0.8555% −0.3824%] (p = 0.00 < 
0.05)
                           Change within noise threshold.
   Found 2 outliers among 100 measurements (2.00%)
     2 (2.00%) high severe
   
   word_to_ident/clone_into_ident_100x
                           time:   [1.8360 µs 1.8463 µs 1.8572 µs]
                           change: [+2.2347% +2.8474% +3.5024%] (p = 0.00 < 
0.05)
                           Performance has regressed.
   word_to_ident/to_ident_100x
                           time:   [1.5207 µs 1.5263 µs 1.5319 µs]
                           change: [+2.5991% +3.0039% +3.4031%] (p = 0.00 < 
0.05)
                           Performance has regressed.
   Found 3 outliers among 100 measurements (3.00%)
     2 (2.00%) high mild
     1 (1.00%) high severe
   
   parse_identifiers/select_100_columns
                           time:   [71.498 µs 72.063 µs 72.674 µs]
                           change: [−6.9631% −6.2297% −5.5577%] (p = 0.00 < 
0.05)
                           Performance has improved.
   Found 12 outliers among 100 measurements (12.00%)
     6 (6.00%) high mild
     6 (6.00%) high severe
   parse_identifiers/select_100_qualified_columns
                           time:   [151.78 µs 152.03 µs 152.30 µs]
                           change: [−5.3267% −4.6015% −3.4939%] (p = 0.00 < 
0.05)
                           Performance has improved.
   Found 4 outliers among 100 measurements (4.00%)
     1 (1.00%) high mild
     3 (3.00%) high severe
   ```
   </details>
   
   * I was a bit surprised, to see this change actually improve a client 
program (which itself i cannot share, unfortunately):
   <details>
   
   ```
   # ./sqlfmt.sqlparser-main ... built against sqlparser's `main` branch 
(#64f4b1f)
   # ./sqlfmt.sqlparser-function-box ... built ... well against the 
`function-box` branch proposed with this PR (#f8e9e18)
   
   
   > hyperfine -N './sqlfmt.sqlparser-main /tmp/a.sql' 
'./sqlfmt.sqlparser-function-box /tmp/a.sql'
   Benchmark 1: ./sqlfmt.sqlparser-main /tmp/a.sql
     Time (mean ± σ):     373.3 ms ±   2.1 ms    [User: 278.6 ms, System: 94.4 
ms]
     Range (min … max):   370.2 ms … 377.9 ms    10 runs
   
   Benchmark 2: ./sqlfmt.sqlparser-function-box /tmp/a.sql
     Time (mean ± σ):     345.7 ms ±   1.5 ms    [User: 254.3 ms, System: 91.2 
ms]
     Range (min … max):   343.2 ms … 348.4 ms    10 runs
   
   Summary
     ./sqlfmt.sqlparser-function-box /tmp/a.sql ran
       1.08 ± 0.01 times faster than ./sqlfmt.sqlparser-main /tmp/a.sql
   
   
   > hyperfine -N './sqlfmt.sqlparser-main --optimize-column-aliases 
/tmp/a.sql' './sqlfmt.sqlparser-function-box --optimize-column-aliases 
/tmp/a.sql'
   Benchmark 1: ./sqlfmt.sqlparser-main --optimize-column-aliases /tmp/a.sql
     Time (mean ± σ):     411.9 ms ±   7.6 ms    [User: 311.3 ms, System: 100.3 
ms]
     Range (min … max):   405.7 ms … 430.7 ms    10 runs
   
   Benchmark 2: ./sqlfmt.sqlparser-function-box --optimize-column-aliases 
/tmp/a.sql
     Time (mean ± σ):     381.2 ms ±   2.8 ms    [User: 292.0 ms, System: 88.9 
ms]
     Range (min … max):   377.8 ms … 386.4 ms    10 runs
   
   Summary
     ./sqlfmt.sqlparser-function-box --optimize-column-aliases /tmp/a.sql ran
       1.08 ± 0.02 times faster than ./sqlfmt.sqlparser-main 
--optimize-column-aliases /tmp/a.sql
   
   
   # the input file (/tmp/a.sql) is some ~50k lines of sql (approx 3.1mb) with 
some  monster select
   #    from oracle's apex  repeated approx 100 times
   
   # the "--optimize-column-aliases" causes the program to traverse the AST a 
several times
   #      and allocate quite a lot of string, in other words it's inefficient, 
but that's the only different.
   #     Notably the absolute speed up is - more or less - the same for both 
versions, indicating
   #    a real win through the boxing in sqlparser's `Expr::Function`.
   ```
   </details>
   
   * My theory here is that by reducing the size of the `enum` CPU caches get 
better utilised manifesting in faster performance (at least when reading the 
AST.)
   * `Expr` itself, could further _practically_ be reduced to about 80-100 
bytes, though i'm not able to tell how much improvement that could contribute. 
(i've marked some candidates with `XXX` in this pr.)
   * Other `enum`s/`struct`s, chiefly `Statement`, could be considered for this 
kind of change. there are really huge differences in sizes of the individual 
enum variants, leading `Parser::parse` (and related) to return needlessly large 
memory chunks (on average, of course.) `Expr` seemed very much prevalent in the 
AST, so i suppose this would be the biggest win / lowest hanging fruit.
   * The biggest issue with this change are tests, though; we cannot pattern 
match on a `Box` is Rust, making it a pain in the neck to (re)write them 
without some additional helper functions (in this PR i just went straight to 
make it work without a lot of thought.)
   * I would be glad if somebody could confirm or refute my theory. or maybe 
just run this change on some other machines. maybe @iffyio, @LucaCappelletti94, 
or @eyalleshem if you'd be interested?
   * I'm keeping this as a draft for now, since my primary intention is first 
to trigger a discussion on how the API could (or not) evolve.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to