Keats / tera

A template engine for Rust based on Jinja2/Django
http://keats.github.io/tera/
MIT License
3.44k stars 280 forks source link

Custom dotted_pointer implementation #812

Closed godofdream closed 1 year ago

godofdream commented 1 year ago

get_json_pointer converted a dotted pointer to an slashed pointer for serde jsons pointer. I replaced the used of pointer(get_json_pointer()) with an implementation of dotted_pointer what reduced a lot of allocations

as get_json_pointer was hidden, but a public function (for benchmarks), I marked it as deprecated.

benchmarks got replaced by a benchmark that uses dotted_pointer in a serde json value.

This improvement is not a breaking change.

Benchmarks before:

running 4 tests
test bench_big_loop_big_object                 ... bench:     184,662 ns/iter (+/- 2,075)
test bench_macro_big_object                    ... bench:     445,885 ns/iter (+/- 9,864)
test bench_macro_big_object_no_loop_macro_call ... bench:   1,052,077 ns/iter (+/- 152,796)
test bench_macro_big_object_no_loop_with_set   ... bench:   1,040,018 ns/iter (+/- 96,262)

test result: ok. 0 passed; 0 failed; 0 ignored; 4 measured; 0 filtered out; finished in 10.07s

     Running benches/escaping.rs (target/release/deps/escaping-73cdee30956e38a2)

running 6 tests
test bench_escape_html_long         ... bench:         297 ns/iter (+/- 6)
test bench_escape_html_short        ... bench:         126 ns/iter (+/- 3)
test bench_escape_html_very_long    ... bench:       4,127 ns/iter (+/- 34)
test bench_escape_no_html_long      ... bench:         295 ns/iter (+/- 3)
test bench_escape_no_html_short     ... bench:          99 ns/iter (+/- 53)
test bench_escape_no_html_very_long ... bench:       2,374 ns/iter (+/- 48)

test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out; finished in 11.67s

     Running benches/json_pointer.rs (target/release/deps/json_pointer-82582d912d61dd99)

running 2 tests
test bench_get_json_pointer          ... bench:         114 ns/iter (+/- 6)
test bench_get_json_pointer_with_map ... bench:         566 ns/iter (+/- 9)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 0.62s

     Running benches/templates.rs (target/release/deps/templates-2b7e84ae09e9002a)

running 2 tests
test big_table ... bench:   1,400,942 ns/iter (+/- 47,474)
test teams     ... bench:       4,410 ns/iter (+/- 47)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 3.20s

     Running benches/tera.rs (target/release/deps/tera-c384b6304625628d)

running 12 tests
test access_deep_object                        ... bench:       2,694 ns/iter (+/- 144)
test access_deep_object_with_literal           ... bench:       4,508 ns/iter (+/- 97)
test bench_build_inheritance_chains            ... bench:       2,181 ns/iter (+/- 147)
test bench_huge_loop                           ... bench:     593,874 ns/iter (+/- 20,272)
test bench_parsing_basic_template              ... bench:      44,001 ns/iter (+/- 423)
test bench_parsing_with_inheritance_and_macros ... bench:      69,565 ns/iter (+/- 534)
test bench_rendering_basic_template            ... bench:       3,626 ns/iter (+/- 112)
test bench_rendering_inheritance_and_macros    ... bench:       4,094 ns/iter (+/- 75)
test bench_rendering_only_inheritance          ... bench:         933 ns/iter (+/- 17)
test bench_rendering_only_macro_call           ... bench:       3,342 ns/iter (+/- 35)
test bench_rendering_only_parent               ... bench:         398 ns/iter (+/- 7)
test bench_rendering_only_variable             ... bench:         779 ns/iter (+/- 6)

test result: ok. 0 passed; 0 failed; 0 ignored; 12 measured; 0 filtered out; finished in 7.48s

Benchmarks after:

running 4 tests
test bench_big_loop_big_object                 ... bench:     186,405 ns/iter (+/- 1,487)
test bench_macro_big_object                    ... bench:     371,849 ns/iter (+/- 10,331)
test bench_macro_big_object_no_loop_macro_call ... bench:   1,021,208 ns/iter (+/- 95,960)
test bench_macro_big_object_no_loop_with_set   ... bench:   1,028,662 ns/iter (+/- 39,664)

test result: ok. 0 passed; 0 failed; 0 ignored; 4 measured; 0 filtered out; finished in 6.73s

     Running benches/dotted_pointer.rs (target/release/deps/dotted_pointer-4b5732f0741af2c5)

running 2 tests
test bench_get_dotted_pointer          ... bench:         285 ns/iter (+/- 2)
test bench_get_dotted_pointer_with_map ... bench:         288 ns/iter (+/- 1)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 4.04s

     Running benches/escaping.rs (target/release/deps/escaping-73cdee30956e38a2)

running 6 tests
test bench_escape_html_long         ... bench:         284 ns/iter (+/- 11)
test bench_escape_html_short        ... bench:         116 ns/iter (+/- 6)
test bench_escape_html_very_long    ... bench:       4,128 ns/iter (+/- 56)
test bench_escape_no_html_long      ... bench:         454 ns/iter (+/- 15)
test bench_escape_no_html_short     ... bench:         139 ns/iter (+/- 2)
test bench_escape_no_html_very_long ... bench:       1,400 ns/iter (+/- 8)

test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out; finished in 3.98s

     Running benches/templates.rs (target/release/deps/templates-2b7e84ae09e9002a)

running 2 tests
test big_table ... bench:   1,432,697 ns/iter (+/- 76,929)
test teams     ... bench:       3,578 ns/iter (+/- 119)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 4.55s

     Running benches/tera.rs (target/release/deps/tera-c384b6304625628d)

running 12 tests
test access_deep_object                        ... bench:       2,071 ns/iter (+/- 59)
test access_deep_object_with_literal           ... bench:       3,770 ns/iter (+/- 33)
test bench_build_inheritance_chains            ... bench:       2,035 ns/iter (+/- 30)
test bench_huge_loop                           ... bench:     509,551 ns/iter (+/- 13,032)
test bench_parsing_basic_template              ... bench:      43,277 ns/iter (+/- 590)
test bench_parsing_with_inheritance_and_macros ... bench:      68,536 ns/iter (+/- 857)
test bench_rendering_basic_template            ... bench:       2,830 ns/iter (+/- 61)
test bench_rendering_inheritance_and_macros    ... bench:       3,554 ns/iter (+/- 57)
test bench_rendering_only_inheritance          ... bench:         914 ns/iter (+/- 19)
test bench_rendering_only_macro_call           ... bench:       2,839 ns/iter (+/- 85)
test bench_rendering_only_parent               ... bench:         384 ns/iter (+/- 14)
test bench_rendering_only_variable             ... bench:         595 ns/iter (+/- 18)

test result: ok. 0 passed; 0 failed; 0 ignored; 12 measured; 0 filtered out; finished in 6.58s
godofdream commented 1 year ago

I further improved the implementation by removing the regex:

With Regex:

running 4 tests
test bench_big_loop_big_object                 ... bench:     204,544 ns/iter (+/- 1,979)
test bench_macro_big_object                    ... bench:     479,748 ns/iter (+/- 6,731)
test bench_macro_big_object_no_loop_macro_call ... bench:   1,096,932 ns/iter (+/- 289,113)
test bench_macro_big_object_no_loop_with_set   ... bench:   1,133,226 ns/iter (+/- 84,247)

test result: ok. 0 passed; 0 failed; 0 ignored; 4 measured; 0 filtered out; finished in 7.66s

     Running benches/dotted_pointer.rs (target/release/deps/dotted_pointer-4b5732f0741af2c5)

running 2 tests
test bench_get_dotted_pointer          ... bench:         560 ns/iter (+/- 8)
test bench_get_dotted_pointer_with_map ... bench:         625 ns/iter (+/- 13)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 0.49s

     Running benches/escaping.rs (target/release/deps/escaping-73cdee30956e38a2)

running 6 tests
test bench_escape_html_long         ... bench:         284 ns/iter (+/- 19)
test bench_escape_html_short        ... bench:         126 ns/iter (+/- 14)
test bench_escape_html_very_long    ... bench:       6,430 ns/iter (+/- 105)
test bench_escape_no_html_long      ... bench:         454 ns/iter (+/- 10)
test bench_escape_no_html_short     ... bench:         140 ns/iter (+/- 3)
test bench_escape_no_html_very_long ... bench:       2,333 ns/iter (+/- 41)

test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out; finished in 8.90s

     Running benches/templates.rs (target/release/deps/templates-2b7e84ae09e9002a)

running 2 tests
test big_table ... bench:   1,442,589 ns/iter (+/- 21,850)
test teams     ... bench:       4,643 ns/iter (+/- 159)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 6.26s

     Running benches/tera.rs (target/release/deps/tera-c384b6304625628d)

running 12 tests
test access_deep_object                        ... bench:       3,085 ns/iter (+/- 127)
test access_deep_object_with_literal           ... bench:       4,448 ns/iter (+/- 92)
test bench_build_inheritance_chains            ... bench:       2,153 ns/iter (+/- 24)
test bench_huge_loop                           ... bench:     614,457 ns/iter (+/- 9,516)
test bench_parsing_basic_template              ... bench:      43,449 ns/iter (+/- 1,820)
test bench_parsing_with_inheritance_and_macros ... bench:      68,384 ns/iter (+/- 3,733)
test bench_rendering_basic_template            ... bench:       3,629 ns/iter (+/- 160)
test bench_rendering_inheritance_and_macros    ... bench:       4,219 ns/iter (+/- 114)
test bench_rendering_only_inheritance          ... bench:         931 ns/iter (+/- 16)
test bench_rendering_only_macro_call           ... bench:       3,412 ns/iter (+/- 74)
test bench_rendering_only_parent               ... bench:         388 ns/iter (+/- 7)
test bench_rendering_only_variable             ... bench:         787 ns/iter (+/- 28)

test result: ok. 0 passed; 0 failed; 0 ignored; 12 measured; 0 filtered out; finished in 7.01s

With Automata:

running 4 tests
test bench_big_loop_big_object                 ... bench:     186,401 ns/iter (+/- 2,597)
test bench_macro_big_object                    ... bench:     401,469 ns/iter (+/- 8,237)
test bench_macro_big_object_no_loop_macro_call ... bench:   1,035,573 ns/iter (+/- 76,263)
test bench_macro_big_object_no_loop_with_set   ... bench:   1,022,571 ns/iter (+/- 29,829)

test result: ok. 0 passed; 0 failed; 0 ignored; 4 measured; 0 filtered out; finished in 6.57s

     Running benches/dotted_pointer.rs (target/release/deps/dotted_pointer-4b5732f0741af2c5)

running 2 tests
test bench_get_dotted_pointer          ... bench:         299 ns/iter (+/- 15)
test bench_get_dotted_pointer_with_map ... bench:         372 ns/iter (+/- 20)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 0.88s

     Running benches/escaping.rs (target/release/deps/escaping-73cdee30956e38a2)

running 6 tests
test bench_escape_html_long         ... bench:         284 ns/iter (+/- 11)
test bench_escape_html_short        ... bench:         129 ns/iter (+/- 1)
test bench_escape_html_very_long    ... bench:       6,405 ns/iter (+/- 274)
test bench_escape_no_html_long      ... bench:         454 ns/iter (+/- 12)
test bench_escape_no_html_short     ... bench:         140 ns/iter (+/- 12)
test bench_escape_no_html_very_long ... bench:       2,342 ns/iter (+/- 43)

test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out; finished in 4.02s

     Running benches/templates.rs (target/release/deps/templates-2b7e84ae09e9002a)

running 2 tests
test big_table ... bench:   1,389,428 ns/iter (+/- 66,400)
test teams     ... bench:       3,733 ns/iter (+/- 108)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 8.17s

     Running benches/tera.rs (target/release/deps/tera-c384b6304625628d)

running 12 tests
test access_deep_object                        ... bench:       2,162 ns/iter (+/- 496)
test access_deep_object_with_literal           ... bench:       3,498 ns/iter (+/- 53)
test bench_build_inheritance_chains            ... bench:       2,039 ns/iter (+/- 28)
test bench_huge_loop                           ... bench:     514,174 ns/iter (+/- 6,731)
test bench_parsing_basic_template              ... bench:      44,501 ns/iter (+/- 193)
test bench_parsing_with_inheritance_and_macros ... bench:      68,430 ns/iter (+/- 407)
test bench_rendering_basic_template            ... bench:       2,889 ns/iter (+/- 54)
test bench_rendering_inheritance_and_macros    ... bench:       3,689 ns/iter (+/- 50)
test bench_rendering_only_inheritance          ... bench:         939 ns/iter (+/- 23)
test bench_rendering_only_macro_call           ... bench:       2,934 ns/iter (+/- 121)
test bench_rendering_only_parent               ... bench:         390 ns/iter (+/- 10)
test bench_rendering_only_variable             ... bench:         620 ns/iter (+/- 46)

test result: ok. 0 passed; 0 failed; 0 ignored; 12 measured; 0 filtered out; finished in 5.47s
Keats commented 1 year ago

(FYI I don't know if you are familiar with it but https://github.com/BurntSushi/cargo-benchcmp is great to see the changes visually)

godofdream commented 1 year ago

benchcmp:

 name                                       control ns/iter  custom_pointer_implementation ns/iter  diff ns/iter   diff %  speedup 
 access_deep_object                         2,611            2,273                                          -338  -12.95%   x 1.15 
 access_deep_object_with_literal            4,326            3,530                                          -796  -18.40%   x 1.23 
 bench_big_loop_big_object                  186,333          185,196                                      -1,137   -0.61%   x 1.01 
 bench_build_inheritance_chains             2,198            2,005                                          -193   -8.78%   x 1.10 
 bench_escape_html_long                     456              452                                              -4   -0.88%   x 1.01 
 bench_escape_html_short                    129              129                                               0    0.00%   x 1.00 
 bench_escape_html_very_long                6,473            6,427                                           -46   -0.71%   x 1.01 
 bench_escape_no_html_long                  455              452                                              -3   -0.66%   x 1.01 
 bench_escape_no_html_short                 140              140                                               0    0.00%   x 1.00 
 bench_escape_no_html_very_long             2,324            2,334                                            10    0.43%   x 1.00 
 bench_huge_loop                            614,181          540,741                                     -73,440  -11.96%   x 1.14 
 bench_macro_big_object                     451,575          396,760                                     -54,815  -12.14%   x 1.14 
 bench_macro_big_object_no_loop_macro_call  1,022,069        1,042,575                                    20,506    2.01%   x 0.98 
 bench_macro_big_object_no_loop_with_set    1,024,800        1,034,063                                     9,263    0.90%   x 0.99 
 bench_parsing_basic_template               44,533           44,281                                         -252   -0.57%   x 1.01 
 bench_parsing_with_inheritance_and_macros  69,851           69,357                                         -494   -0.71%   x 1.01 
 bench_rendering_basic_template             3,575            2,980                                          -595  -16.64%   x 1.20 
 bench_rendering_inheritance_and_macros     4,059            3,785                                          -274   -6.75%   x 1.07 
 bench_rendering_only_inheritance           997              924                                             -73   -7.32%   x 1.08 
 bench_rendering_only_macro_call            3,301            3,033                                          -268   -8.12%   x 1.09 
 bench_rendering_only_parent                379              410                                              31    8.18%   x 0.92 
 bench_rendering_only_variable              816              636                                            -180  -22.06%   x 1.28 
 big_table                                  1,462,393        1,381,290                                   -81,103   -5.55%   x 1.06 
 teams                                      4,315            3,726                                          -589  -13.65%   x 1.16