Skip to content

feat(static): add static package as a DCE-friendly alternative#956

Closed
vincentbernat wants to merge 1 commit intoexpr-lang:masterfrom
vincentbernat:feature/dce-elimination
Closed

feat(static): add static package as a DCE-friendly alternative#956
vincentbernat wants to merge 1 commit intoexpr-lang:masterfrom
vincentbernat:feature/dce-elimination

Conversation

@vincentbernat
Copy link
Copy Markdown
Contributor

The package is a drop-in replacement with two features removed:

  • functions in environment
  • Eval() method

The changes are quite minimal and I am using go generate to copy expr.go to v2/expr.go. The full user interface is therefore not present in expr.go anymore. We could keep Eval() and make it panic instead.

Fix #863.

The package is a drop-in replacement with two features removed:
- functions in environment
- Eval() method

Fix expr-lang#863.
@vincentbernat
Copy link
Copy Markdown
Contributor Author

Dunno why the coverage test fails.

Some benchmarks:

goos: linux
goarch: amd64
pkg: github.com/expr-lang/expr
cpu: AMD Ryzen 5 5600X 6-Core Processor
                            │ before.txt  │              after.txt              │
                            │   sec/op    │    sec/op     vs base               │
_expr-12                      85.63n ± 1%   79.22n ±  4%   -7.49% (p=0.002 n=6)
_expr_eval-12                 5.781µ ± 1%   5.994µ ±  2%   +3.68% (p=0.002 n=6)
_expr_reuseVm-12              60.66n ± 3%   53.55n ±  2%  -11.72% (p=0.002 n=6)
_len-12                       48.46n ± 4%   47.82n ±  1%   -1.32% (p=0.004 n=6)
_filter-12                    42.43µ ± 2%   43.10µ ±  1%   +1.58% (p=0.041 n=6)
_filterLen-12                 37.82µ ± 2%   37.79µ ±  2%        ~ (p=0.699 n=6)
_filterFirst-12               380.0n ± 1%   383.9n ± 10%   +1.03% (p=0.039 n=6)
_filterLast-12                716.7n ± 2%   684.9n ±  2%   -4.44% (p=0.002 n=6)
_filterMap-12                 3.861µ ± 3%   3.829µ ±  1%        ~ (p=0.258 n=6)
_arrayIndex-12                84.54n ± 2%   86.55n ±  2%        ~ (p=0.065 n=6)
_envStruct-12                 53.07n ± 1%   55.24n ±  4%   +4.10% (p=0.002 n=6)
_envStruct_noEnv-12           140.5n ± 2%   141.3n ±  1%        ~ (p=0.394 n=6)
_envMap-12                    64.05n ± 3%   60.57n ±  1%   -5.43% (p=0.002 n=6)
_callFunc-12                  348.0n ± 6%   358.9n ±  1%        ~ (p=0.058 n=6)
_callMethod-12                365.4n ± 1%   382.8n ±  1%   +4.75% (p=0.002 n=6)
_callField-12                 75.81n ± 2%   74.95n ±  0%   -1.13% (p=0.004 n=6)
_callFast-12                  76.38n ± 3%   76.66n ±  2%        ~ (p=0.937 n=6)
_callConstExpr-12             35.02n ± 1%   35.37n ±  2%        ~ (p=0.240 n=6)
_largeStructAccess-12         138.4n ± 1%   144.2n ±  5%   +4.26% (p=0.002 n=6)
_largeNestedStructAccess-12   148.0n ± 1%   160.8n ±  1%   +8.65% (p=0.002 n=6)
_largeNestedArrayAccess-12    1.073m ± 8%   1.064m ±  9%        ~ (p=0.937 n=6)
_sort-12                      3.948µ ± 1%   4.493µ ±  1%  +13.80% (p=0.002 n=6)
_sortBy-12                    11.33µ ± 3%   11.24µ ±  1%        ~ (p=0.132 n=6)
_groupBy-12                   8.259µ ± 1%   7.964µ ±  2%   -3.57% (p=0.002 n=6)
_reduce-12                    34.64n ± 1%   34.59n ±  2%        ~ (p=0.818 n=6)
_min-12                       500.6n ± 1%   496.3n ±  1%   -0.86% (p=0.026 n=6)
_max-12                       506.7n ± 1%   504.8n ±  1%   -0.37% (p=0.013 n=6)
_mean-12                      218.1n ± 2%   220.3n ±  2%        ~ (p=0.221 n=6)
_median-12                    1.599µ ± 1%   1.631µ ±  1%   +2.03% (p=0.002 n=6)
geomean                       564.7n        566.7n         +0.36%

pkg: github.com/expr-lang/expr/checker
                                            │ before.txt  │             after.txt              │
                                            │   sec/op    │   sec/op     vs base               │
Checker/name=function_calls-12                6.248µ ± 5%   6.098µ ± 3%        ~ (p=0.093 n=6)
Checker/name=unary_and_binary_operations-12   6.167µ ± 3%   6.309µ ± 3%   +2.30% (p=0.026 n=6)
Checker/name=deep_struct_access-12            16.48µ ± 2%   21.50µ ± 1%  +30.48% (p=0.002 n=6)
geomean                                       8.594µ        9.387µ        +9.22%

pkg: github.com/expr-lang/expr/internal/difflib
                   │ before.txt  │             after.txt             │
                   │   sec/op    │   sec/op     vs base              │
SplitLines100-12     905.9n ± 1%   841.1n ± 1%  -7.15% (p=0.002 n=6)
SplitLines10000-12   81.46µ ± 1%   79.75µ ± 3%       ~ (p=0.065 n=6)
geomean              8.590µ        8.190µ       -4.66%

pkg: github.com/expr-lang/expr/internal/testify/assert
              │ before.txt  │             after.txt             │
              │   sec/op    │   sec/op     vs base              │
BytesEqual-12   144.9n ± 5%   143.6n ± 3%       ~ (p=0.506 n=6)
NotNil-12       4.416n ± 1%   4.379n ± 2%       ~ (p=0.485 n=6)
geomean         25.29n        25.08n       -0.85%

pkg: github.com/expr-lang/expr/optimizer
                                 │ before.txt  │             after.txt              │
                                 │   sec/op    │   sec/op     vs base               │
CountGtZero-12                     1.438µ ± 3%   1.343µ ± 1%   -6.61% (p=0.002 n=6)
CountGtZeroLargeEarlyMatch-12      9.107µ ± 7%   9.317µ ± 6%        ~ (p=0.310 n=6)
CountGtZeroNoMatch-12              29.32µ ± 4%   29.55µ ± 1%        ~ (p=0.485 n=6)
CountGteOneEarlyMatch-12           1.452µ ± 2%   1.339µ ± 5%   -7.82% (p=0.002 n=6)
CountGteOneNoMatch-12              29.22µ ± 5%   28.98µ ± 1%        ~ (p=0.065 n=6)
CountThresholdEarlyMatch-12        15.00µ ± 3%   13.19µ ± 1%  -12.06% (p=0.002 n=6)
CountThresholdGteEarlyMatch-12     12.20µ ± 2%   10.84µ ± 3%  -11.12% (p=0.002 n=6)
CountThresholdNoEarlyExit-12       342.4µ ± 2%   333.6µ ± 2%   -2.59% (p=0.009 n=6)
CountThresholdLargeEarlyMatch-12   89.66µ ± 2%   83.75µ ± 5%   -6.59% (p=0.004 n=6)
CountThresholdLtEarlyExit-12       15.56µ ± 9%   13.16µ ± 8%  -15.42% (p=0.002 n=6)
CountThresholdLteEarlyExit-12      12.45µ ± 3%   11.50µ ± 7%   -7.70% (p=0.002 n=6)
CountThresholdLtNoEarlyExit-12     340.8µ ± 3%   349.7µ ± 2%        ~ (p=0.093 n=6)
CountThresholdLteNoEarlyExit-12    353.2µ ± 3%   348.9µ ± 5%        ~ (p=0.394 n=6)
SumArray-12                        187.1n ± 4%   149.0n ± 5%  -20.39% (p=0.002 n=6)
SumRange_Optimized-12              35.64n ± 7%   36.22n ± 2%        ~ (p=0.701 n=6)
ReduceRangeSum_Optimized-12        35.45n ± 6%   35.03n ± 5%        ~ (p=0.485 n=6)
SumRange_Unoptimized-12            3.267µ ± 4%   3.369µ ± 2%        ~ (p=0.065 n=6)
geomean                            7.854µ        7.451µ        -5.13%

pkg: github.com/expr-lang/expr/parser
          │  before.txt  │             after.txt             │
          │    sec/op    │   sec/op     vs base              │
Parser-12   618.2n ± 13%   588.3n ± 2%  -4.84% (p=0.002 n=6)

          │ before.txt │           after.txt           │
          │    B/op    │    B/op     vs base           │
Parser-12   256.0 ± 0%   256.0 ± 0%  ~ (p=1.000 n=6) ¹
¹ all samples are equal

          │ before.txt │           after.txt           │
          │ allocs/op  │ allocs/op   vs base           │
Parser-12   8.000 ± 0%   8.000 ± 0%  ~ (p=1.000 n=6) ¹
¹ all samples are equal

pkg: github.com/expr-lang/expr/patcher/value
                    │ before.txt  │             after.txt             │
                    │   sec/op    │   sec/op     vs base              │
_valueAdd-12          86.08n ± 1%   90.62n ± 3%  +5.27% (p=0.002 n=6)
_valueUntypedAdd-12   102.7n ± 2%   110.8n ± 2%  +7.94% (p=0.002 n=6)
_valueTypedAdd-12     84.59n ± 1%   89.58n ± 3%  +5.90% (p=0.002 n=6)
geomean               90.75n        96.53n       +6.36%

pkg: github.com/expr-lang/expr/test/bench
                  │ before.txt  │             after.txt             │
                  │   sec/op    │   sec/op     vs base              │
Call_callTyped-12   8.686µ ± 1%   8.832µ ± 2%  +1.68% (p=0.002 n=6)
Call_eval-12        1.619µ ± 1%   1.684µ ± 2%  +4.01% (p=0.002 n=6)
geomean             3.750µ        3.856µ       +2.84%

pkg: github.com/expr-lang/expr/vm
                          │ before.txt  │          after.txt           │
                          │   sec/op    │   sec/op     vs base         │
VM/name=function_calls-12   1.670µ ± 1%   1.637µ ± 4%  ~ (p=0.058 n=6)

pkg: github.com/expr-lang/expr/vm/runtime
                                          │ before.txt  │              after.txt              │
                                          │   sec/op    │    sec/op     vs base               │
Equal/int_==_int-12                         2.163n ± 1%   2.200n ±  3%   +1.71% (p=0.009 n=6)
Equal/int_!=_int-12                         2.165n ± 0%   2.196n ±  1%   +1.45% (p=0.004 n=6)
Equal/int_==_int8-12                        2.379n ± 0%   2.406n ±  1%   +1.11% (p=0.002 n=6)
Equal/int_==_int16-12                       2.381n ± 0%   2.419n ±  4%   +1.60% (p=0.004 n=6)
Equal/int_==_int32-12                       2.188n ± 2%   2.240n ±  2%   +2.38% (p=0.013 n=6)
Equal/int_==_int64-12                       2.399n ± 1%   2.397n ±  1%        ~ (p=0.699 n=6)
Equal/float_==_float-12                     2.384n ± 1%   2.400n ±  3%   +0.65% (p=0.041 n=6)
Equal/float_!=_float-12                     2.384n ± 0%   2.401n ±  1%   +0.67% (p=0.004 n=6)
Equal/float_==_int-12                       2.606n ± 0%   2.621n ±  1%   +0.59% (p=0.030 n=6)
Equal/float_!=_int-12                       2.607n ± 2%   4.617n ± 43%  +77.10% (p=0.004 n=6)
Equal/string_==_string-12                   3.244n ± 2%   3.329n ± 85%   +2.64% (p=0.015 n=6)
Equal/string_!=_string-12                   4.547n ± 1%   4.547n ±  0%        ~ (p=0.853 n=6)
Equal/bool_==_bool-12                       2.165n ± 0%   2.174n ±  1%   +0.39% (p=0.024 n=6)
Equal/bool_!=_bool-12                       2.167n ± 0%   2.169n ±  0%        ~ (p=0.866 n=6)
Equal/[]any_==_[]int-12                     15.18n ± 6%   15.49n ±  5%        ~ (p=0.981 n=6)
Equal/[]any_!=_[]int-12                     15.50n ± 8%   14.80n ±  6%        ~ (p=0.457 n=6)
Equal/deep_[]any_==_[]any-12                84.08n ± 1%   84.36n ± 11%        ~ (p=0.310 n=6)
Equal/deep_[]any_!=_[]any-12                61.08n ± 2%   61.41n ±  7%        ~ (p=0.132 n=6)
Equal/map[string]any_==_map[string]any-12   253.5n ± 1%   254.4n ±  2%        ~ (p=0.240 n=6)
Equal/map[string]any_!=_map[string]any-12   59.46n ± 1%   59.56n ±  0%        ~ (p=0.848 n=6)
geomean                                     6.188n        6.405n         +3.51%

I didn't try to adapt the benchmark for the "static" version. Maybe we will get better results.

@antonmedv
Copy link
Copy Markdown
Member

I was thinking about creating a build tag: expr_nomethod.

@vincentbernat
Copy link
Copy Markdown
Contributor Author

vincentbernat commented Apr 26, 2026

I was thinking about creating a build tag: expr_nomethod.

Yes, it should have 0 performance impact as Go should be able to eliminate the additional tests. Do you want me to do a PR for that? Most of this PR can be reused for this.

Edit: I am working on it.

@antonmedv
Copy link
Copy Markdown
Member

Nice!

Seems like still one test is failing in coverage.

@vincentbernat
Copy link
Copy Markdown
Contributor Author

Seems like still one test is failing in coverage.

In this pull request, yes, but not in #957. Let me close this one.

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.

Avoid reflect.MethodByName

2 participants