Skip to content

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

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

feat(static): add static package as a DCE-friendly alternative#956
vincentbernat wants to merge 1 commit into
expr-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

vincentbernat commented Apr 26, 2026

Copy link
Copy Markdown
Contributor Author

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