-
-
Notifications
You must be signed in to change notification settings - Fork 94
Closed
Description
Originated from #468
TLDR; Interpreter to reduce the IL emitted by the Logical, Comparison, Arithmetics expressions,
by calculating them during compile time and using the calculation result in IL.
Considerations:
- Add the compilation flag to switch off the Interpretation.
- @Perf For the performance to avoid the boxing as much as possible.
- @Perf Try to minimize recursion, for instance check for the Constant and use it value before the recursive call, as the constants are the leafs of the interpreted expression tree, they take 1/2 of the total calls.
- @Perf FEC does two traversals for Expression, first to gather Closure info and second to Emit. The heavy call to creating the DynamicMethod is happening after 1st traversal. Maybe we can try Interpreter in this first stage to avoid DynamicMethod creation at all?
- @Perf We need a fast negative check before try the Interpretation. It should be upfront before any method call or
try catch. We might be not interested in checking for the Constant or Default, because the result IL will be the same simple thing either for the Interpretation or Compilation - For the Constants and other expressions when evaluating the comparison, start with the
ReferenceEqualscomparison of the expressions themselves @wip - For the short-circuiting logical OrElse and AnAlso operations, no need to evaluate the right sub-expression, if the left provides the answer. In this case the right may be of whatever complexity, not limited to just Constant, Convert, Arithmetic, etc.
- Interpreter may be used before the Compilation even start, e.g. for the
Func<bool>delegates and if possible return predefined TrueFunc and FalseFunc avoiding Compilation altogether. - Collect the statistics for the tests, how often Interpretation has been applied.
- @wip Cover more types in interpreter, e.g. DateTime, Char, String
- @wip What about the Nullable?
- Supported expressions: - Constant
- Default
- Convert
- Logical: AndAlso, OrElse, Not
- Comparison: Equal, NotEqual, GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual
- Arithemtic: Negate, Add, Subtract, Mutliply, Divide, Modulo, Or, And, ExclusiveOr, RightShift, LeftShift
- @wip Power and the
...Checkedarithmetic variants - @wip Support read-only Field and Property access, e.g. to get length of the string constant
"foo".Length
Small removal of the boxing around the bool for the expression ((1 + 2) == (5 + -2)) == (42 == 42) leads to the following results:
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
Intel Core i9-8950HK CPU 2.90GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 9.0.203
[Host] : .NET 9.0.4 (9.0.425.16305), X64 RyuJIT AVX2
DefaultJob : .NET 9.0.4 (9.0.425.16305), X64 RyuJIT AVX2
| Method | Mean | Error | StdDev | Ratio | RatioSD | Rank | Gen0 | Allocated | Alloc Ratio |
|---------- |----------:|----------:|----------:|------:|--------:|-----:|-------:|----------:|------------:|
| Baseline | 13.918 ns | 0.3408 ns | 0.4057 ns | 1.00 | 0.04 | 2 | 0.0076 | 48 B | 1.00 |
| Optimized | 6.986 ns | 0.2011 ns | 0.2819 ns | 0.50 | 0.02 | 1 | - | - | 0.00 |Here is the near final Compilation benchmark:
DefaultJob : .NET 9.0.4 (9.0.425.16305), X64 RyuJIT AVX2
| Method | Mean | Error | StdDev | Ratio | RatioSD | Rank | Gen0 | Gen1 | Allocated | Alloc Ratio |
|-------------------------------- |-------------:|-----------:|-----------:|-------:|--------:|-----:|-------:|-------:|----------:|------------:|
| Compiled | 22,844.78 ns | 327.497 ns | 290.317 ns | 351.80 | 6.40 | 3 | 0.6714 | 0.6409 | 4232 B | NA |
| CompiledFast_DisableInterpreter | 3,089.13 ns | 54.757 ns | 48.541 ns | 47.57 | 0.96 | 2 | 0.1793 | 0.1755 | 1144 B | NA |
| CompiledFast | 64.95 ns | 1.082 ns | 0.903 ns | 1.00 | 0.02 | 1 | - | - | - | NA |
and the Invocation benchmark of the compiled delegate:
DefaultJob : .NET 9.0.4 (9.0.425.16305), X64 RyuJIT AVX2
| Method | Mean | Error | StdDev | Median | Ratio | RatioSD | Rank | BranchInstructions/Op | Allocated | Alloc Ratio |
|-------------------------------------- |----------:|----------:|----------:|----------:|------:|--------:|-----:|----------------------:|----------:|------------:|
| InvokeCompiled | 0.5088 ns | 0.0399 ns | 0.0842 ns | 0.4707 ns | 1.02 | 0.22 | 2 | 1 | - | NA |
| InvokeCompiledFast | 0.1105 ns | 0.0360 ns | 0.0799 ns | 0.0689 ns | 0.22 | 0.16 | 1 | 1 | - | NA |
| InvokeCompiledFast_DisableInterpreter | 1.0607 ns | 0.0540 ns | 0.0887 ns | 1.0301 ns | 2.13 | 0.34 | 3 | 2 | - | NA |Bykiev