Repository navigation
Reduce expression collection and LightExpression construction costs - #559
jogibear9988 wants to merge 202 commits into
Conversation
87187b3 to
73eef09
Compare
|
Rebased this performance layer onto current #558 ( The vector-array classification patch was already present in #558, so it is dropped as redundant. The remaining production increment is the named LightExpression field lookup optimization ( The report compares current master without #558 → current #558 → rebased #559, across 41 workloads, Standard/Light and .NET 8/10. System is shown separately as an unchanged reference, with no before/after delta; its earlier run-to-run variation did not mean System was modified. Fixed-count compilation allocation checks: #558 lower/same/higher = 14/27/0 in each configuration; #559 matches #558 in 41/41. #558's observed compilation-time medians are 4.6–16.9% above master; #559's observed medians are 3.0–4.4% above #558. Standard source is identical across #558/#559, and Light's emitter is identical, so these timing movements do not establish a compilation benefit or a causal Standard regression from the field-lookup patch. Longer Light construction checks show about 32 B less per affected named-field lookup and roughly 5.6–30.1% lower times in the selected affected workloads. All 82 root delegate IL bodies match between #558/#559; no runtime speedup is claimed. Validation: 35,064 imported passes; zero executed failures/crashes; 69 unchanged exclusions. All production/native .NET 8/10/Framework checks and the benchmark-project build pass. Every workload, raw samples, confirmations, separate System references, hashes and validation logs. This remains draft, and #558 was not changed. |
|
One subsequent upstream development: master advanced to |
Use unsigned-source checked conversion opcodes, zero-extend unsigned values widened to Int64, and sign-extend signed integers converted unchecked to UInt64. Apply ConvertChecked semantics and underlying enum conversions before constructing nullable targets. Keep the conversion switch and shared System/Light emitter layout. Add boundary matrices for primitive numeric types and signed/unsigned enums, covering nullable inputs/outputs, null, overflow, NaN, and infinity. Update the existing signed-source IL assertion and propagate ITestX failures to the native runner exit code. Validation: all 1,712 existing native tests plus the new regression methods pass on .NET 10; focused System/Light regressions pass on .NET 8. The 3,407-case imported conversion/coalesce slice improves from 353 failures to 39 failures, with no compiler fallback.
Implement planned nullable bool Not, AndAlso and OrElse support (dadhi#496) in the existing emitter. Share three-valued AND/OR result selection with the non-short-circuit operators while evaluating each operand once and respecting ignored results. Keep the nonnullable paths unchanged and reuse existing locals, nullable accessors and IL emission helpers. Preserve nullable result types in the LightExpression And/AndAlso/OrElse factories using the existing left-typed node. Add shared System/Light truth-table, side-effect, exception, member-access, ignored-result and long-branch regressions, including direct Light factory construction. Require strict compilation in issue dadhi#480 and run its LightExpression variant. Validation: all ten focused imported nullable Boolean cases now pass (previously ten failures). The adjacent logical slice retains its 79 passes and 40 existing custom-operator failures. The native .NET 10 runner passes all 1,712 existing tests and new ITestX regressions; 24 focused regression methods pass across System/Light on .NET 8.
Guard the existing collection and emission reduction loops against null or self reductions. Return the normal unsupported result instead of looping forever; leave system fallback and its validation exceptions unchanged. No extra graph traversal, reduction cache or rewrite phase is introduced. Add native regressions for irreducible and null-reducing nodes, valid reduction chains with parameters, a reduction that stops progressing during emission, strict/throw/fallback contracts, and CompileFastToIL. Validation: native .NET 10 runner passes all existing tests and the new regression groups. All 29 focused System/Light regression methods pass on .NET 8. The imported irreducible-extension cases now terminate immediately; their strict-system exception assertions remain failures because FEC uses its existing unsupported-expression contract.
Use the existing boxing helper before isinst, preserve void operand effects, and emit false for void/pointer targets with nonvoid operands. Keep TypeEqual unsupported. Add shared Standard/LightExpression regressions for nullable, enum, struct, reference, constant and local operands, plus ignored results and side effects. All 28 focused imported type-test cases pass; all 1712 native .NET 10 tests and 37 focused regression methods pass. Broader imported classes still encounter the separate boxed-constant conversion defect.
Register all four regression groups for Standard and LightExpression where supported, including the strict original issue 480 reproduction. Validation: .NET Framework passes 138 TestX methods and 1595 legacy tests with en-US UI culture supplied externally. Both libraries build all configured targets. All 37 new regression methods pass on .NET 8 and .NET 10. The full .NET 8 native runner retains the issue 346 crash reproduced on the parent branch; German UI culture retains two existing issue 261 error-text assertions.
Emit a boxed value for all reference-typed value constants, including ValueType, Enum and interfaces, using the existing constant emitter. Previously only object-typed constants were boxed, leaving invalid stack values that could crash casts and type tests. Add shared Standard/LightExpression ITestX regressions for returned constants, type tests, interface calls and repeated closure constants. Eight new methods pass on .NET 8 and .NET 10; the full .NET 10 native runner passes. The imported cast/as/type-test slice now completes without crashes: 7243 pass and 12 fail across 7255 cases. Remaining failures expose separate ValueType unboxing behavior.
Recognize reference-to-value unboxing through assignment compatibility with the target's underlying value type. Include ValueType and nullable interface/Enum conversions while preserving LightExpression's user-defined conversion lookup. Add shared checked/unchecked parameter and constant matrices comparing values and InvalidCastException/NullReferenceException behavior with the system compiler. Twelve reference regression methods pass on .NET 8 and .NET 10. The full .NET 10 native runner passes, including existing conversion-operator tests. Imported cast/type-test/unary-conversion slice: 7274 pass and two remaining nullable-boxing failures across 7276 cases, with no crashes.
Do not pass instance-call flags when loading nullable arithmetic operands: the emitter stores their values and explicitly takes the temporary address for HasValue/value access. Inlined lambda parameters become locals and previously loaded managed addresses into value slots, producing fatal CLR errors. Add shared ITestX matrices for inlined arguments, block variables and captured parameters across seven primitive types and five operators. Six new methods pass on .NET 10. All 90 imported nullable lambda arithmetic cases now finish without crashes: 76 pass and 14 retain lifted decimal/unsigned division failures. The full .NET 10 native runner passes.
Box nullable values directly when converting to ValueType, Enum or interfaces, preserving null and validating incompatible interface casts. Keep nonnullable conversion paths and user-defined conversion lookup intact. Add shared checked/unchecked constant, parameter and local matrices plus a direct-factory user-defined conversion regression. All 21 imported unary conversion cases pass. The full .NET 10 native runner, including the new regressions and existing exact IL checks, passes.
Extract nullable bounds with Value and use the existing checked numeric conversion helper to emit Int32 bounds before newarr or array construction. Preserve evaluation order and one evaluation per bound, including ignored array results. All 4195 imported ArrayBoundsTests cases pass without crashes. Six new Standard/LightExpression regression methods pass, covering signed/unsigned bounds, nullable null, 64-bit overflow, multidimensional arrays and ignored results.
Look up operators using the underlying nullable operand types after their values have been extracted. This enables the existing lifted arithmetic path for decimal and custom structs, including operators with a different result type. Six new Standard/LightExpression regression methods pass, covering decimal overflow, division by zero, custom structs and DateTime subtraction to TimeSpan. The 90-case imported nullable lambda arithmetic slice now has 86 passes and only four unsigned division failures, with no crashes.
Select div.un for unsigned division in the existing arithmetic opcode dispatch. Cover ordinary, lifted and compound-assignment forms with values crossing the signed range and divide-by-zero exceptions. Six new Standard/LightExpression methods pass. All 138 imported nullable lambda arithmetic and adjacent binary division cases now pass, with no crashes.
Reuse nullable Not emission for primitive nullable complements, emit explicit nonlifted complement operator methods, and preserve operand effects when primitive results are ignored. Clear member-access flags when extracting nullable local values. Seven new regression methods pass, including Standard-only explicit operator methods and shared Standard/LightExpression nullable matrices, member access and ignored results. All 87 imported complement/bitwise-not cases now pass without crashes. LightExpression's unsupported unary-method factory API remains unchanged.
Mark conversion operands as values and dereference nullable by-ref parameters for arithmetic/value contexts, while retaining nullable address behavior for member access. This prevents boxing a managed address when a ref parameter is read inside an array initializer. Four new Standard/LightExpression methods pass for primitive, struct and nullable ref parameters. Combined by-ref conversion and increment/decrement matrices pass all twelve methods on .NET 10; the increment helper correction is a separate following commit.
Use correctly typed one constants, resolve struct/decimal operators, preserve nullable null and wrap small integer overflow in the existing increment helper. Restore a saved nullable operand before incrementing it. Apply the helper to local, parameter, field and ref assignment paths. Eight new Standard/LightExpression regression methods pass, covering pre/post forms, nullable values, custom structs, numeric boundaries and ref parameters. All 1768 imported increment/decrement cases now finish without crashes: 1752 pass and 16 explicit-method cases remain unsupported. Full native suites pass on .NET 8 (1711 legacy tests) and .NET 10 (1712), including the previous baseline .NET 8 issue 346 crash and all registered regressions.
Carry unary operator metadata through the existing assignment/arithmetic emitters. Call supplied methods for primitive and reference values, lift methods accepting underlying values, and call nullable-parameter methods even for null operands. Four Standard-only regression methods compare pre/post results, stored values and call counts for local, parameter, field and ref targets. All 1768 imported increment/decrement cases now pass without crashes. LightExpression's unsupported explicit unary-method factory remains unchanged.
Share receiver-aware dispatch for calls and property/indexer accessors: call struct-declared methods directly and constrain inherited/interface calls. Materialize addresses for value receivers in index get/set and plain member assignment paths, retain ref nullable addresses, and discard ignored getter results. Nullable null comparisons request address operands for HasValue explicitly. Twelve Standard/LightExpression regression methods pass for Object methods, interface methods/properties/indexers, nullable ref receivers and null comparisons, mutable setters and getter side effects. The imported call/index/assignment slice now completes without crashes: 204 pass and 26 fail across 230 cases. No AST classes or public API surface were added.
Treat nullable null constants as nullable operands for relational and lifted comparisons, use unsigned ordering for unsigned strict comparisons, and construct actual nullable Boolean results for lift-to-null comparisons. Emit operands as values and keep result/address metadata consistent. Six shared Standard/LightExpression regression methods pass across parameters, constants, nulls, unsigned boundaries, NaN/infinity, lifted member access and operand side effects. All 350 imported relational/equality cases pass.
Extract and widen non-null nullable left operands, convert fallback values consistently, preserve nullable null and boxing, and resolve implicit decimal conversions. Reuse existing numeric conversion/nullable helpers through a local coalesce conversion helper. Correct LightExpression coalesce inference to consider the unwrapped left type. Six Standard/LightExpression regression methods pass across accepted numeric type pairs, nullable targets, reference results and operand side effects. Imported BinaryCoalesceTests: 179 pass and five explicit conversion-callback cases remain failing across 184 cases.
Evaluate goto values for side effects when the target is void, discard the value, and branch to the actual label, including leave from try/finally. Keep the adjacent-return optimization limited to non-void targets so void labels can continue within the block. Add eight standard/Light regression methods covering Return, Goto and Break values, cleanup, inlining and labels followed by more work. Focused regressions and the full native .NET 10 runner pass.
The .NET Framework system compiler rejects valid implicit nullable-to-decimal coalesces with Unhandled convert. Compare against an explicit HasValue conditional and Convert instead, preserving the full matrix on every framework. Validated all six standard/Light coalesce regression methods on .NET 10 and the full .NET Framework runner: 1,595 legacy tests and all registered TestX groups pass.
Honor explicit unary methods and lift nullable operands through the existing EmitIncOrDec helper, while preserving ignored effects and reading ref operands without assignment. Remove the duplicate primitive-only path. All 208 imported unary increment/decrement cases pass. Five new regression methods pass against the integrated .NET 10 compiler and the isolated .NET 8 compiler.
Limit adjacent-return elimination to terminal labels. Preserve typed label values in existing label locals and branch to the target instead of returning from the containing lambda; retain the existing stack-based loop break convention. Reserve typed return labels before backward jumps. Eight new standard/Light regressions pass, as do all 1,712 native .NET 10 tests. Imported Return/Goto/Break/MakeGoto slice improves from 223 pass / 72 fail to 265 pass / 30 fail (295 cases).
Emit ceq for reference comparisons instead of rediscovering overloaded equality or calling object.Equals. Carry the identity flag through existing Light logical binary nodes, system conversions, and optimized Not(Equal). Eight new standard/Light regression methods pass. Imported reference comparison slice: 422 pass, 8 remaining boxed-constant identity failures out of 430 cases.
CLR 4 allocates 144 bytes for each closed generic constructor resolved with GetMethodFromHandle. Its ordinary empty constructor lookup allocates nothing, and value constructor lookup needs 96 bytes with the existing rented Type array. Use those APIs for Framework only, and avoid initializing unused open handles. Keep modern constructor handles and all closure representations unchanged. Allocation-only causal probe: per-type constructor lookups 288 -> 96 bytes. Separate-process warmed mutable-capture compilation: 5272 -> 5080 bytes (-192). Activation stays 184 bytes, nested invocation 0, factory/invoke 184. Readonly capture8/reference bytes stay unchanged. Forward/reverse fresh-process timing medians observe mutable compilation ratio 0.927; unchanged-path timing variation is retained and is not attributed to this metadata-only change. Validation: normal Standard and Light production builds pass every configured target with zero warnings/errors. CapturedValueRefRegressionTests passes 29 Standard and 32 Light cases on net472, net8.0 and net10.0. Parsing/compilation, activation, nested runtime and factory/runtime measurements captured separately for Framework baseline/current/candidate and modern current/candidate controls. Scratch reproduction and raw data: work/pr558-repair/frame-capture-round2/.
For Framework nested lambdas with user parameters, declare the hidden argument as ArrayClosureWithNonPassedParams. Existing Curry<C,...> already supports this type, so capture accesses no longer need repeated closure casts. Record the private method's exact signature in a status bit; public manual emitter contexts keep their original cast behavior. Keep zero-user-argument signatures unchanged: a separate cached array caused a measured cold allocation regression and was rejected. No closure fields or runtime allocation layout changes. Add regression coverage for private reference captures under exception handling, zero-argument parent signature reuse, Action<T> currying and shared mutation, debug flags, ordinary parent signature rentals and concurrent compilation. Framework warmed and first-use allocation: Func<T> and EH Func<T> compile -120 B; Action<T> -64 B; constant-folded dead capture unchanged. Runtime activation, nested invocation and factory/invoke allocation unchanged. Modern control bytes unchanged. Parsing/runtime timings are captured independently; mixed compiler ratios and VM variability do not establish a CPU guarantee. No extra first-use signature array is allocated by this conservative version. Validation: normal Standard and Light production builds pass all configured targets without warnings/errors. CapturedValueRefRegressionTests: Standard30, Light33 on net472/net8/net10. The broader typed prototype also passed full Framework1003 TestX and1595 legacy tests before zero-argument paths were narrowed back to the existing implementation. Scratch source/raw measurements and the rejected no-argument cold tradeoff remain under work/pr558-repair/frame-capture-*.
Collect eligible root binary operands directly through the existing terminal collector. This avoids JIT-compiling the large scoped visitor for a simple root, without adding a prepass, changing closure storage, or bypassing jump checks on complex trees. Preserve left-to-right failures, constant identity and public cleanup. Trust ordinary Light nodes as requested; explicit intrinsic roots or operands retain their existing collection callbacks and scopes. Measured Standard add warm compile ratios: 0.961 (.NET 8), 0.927 (.NET 10). Nine fresh-process add compile+first medians: -21% / -34%, identical bytes. Framework add cold compile+first: 156.40 -> 118.90 ms; 27080 -> 27040 B. Trusted Light paired add warm compile ratios: 0.961 / 0.920, 872 B unchanged. All measured warmed allocation medians are unchanged, including invocation. Cold and fallback timing controls varied substantially with host load; retain all raw results rather than claim universal CPU parity or speedups. The rejected Light generic-type-provenance prototype added 160/168 B cold and is not included. Add public collector error-order and bound-constant identity regressions, plus Light intrinsic callback/scope regressions. Full native Standard/Light suites: 1712 passing on .NET 10, 1711 on .NET 8. Separate Framework harness checks agree with System results. Evidence: workspace work/pr558-round2/trivial-binary*, to be published with the integrated round-2 report after final validation.
Enable the existing native boxed value-cell representation for nonnullable Framework captures only in the normal fully collecting root entry. Carry that root eligibility through nested contexts and require completed capture analysis. Any exception region anywhere in the root, quote, runtime variables, or unknown node retains the StrongBox representation throughout the root. Manual and collection-skipping APIs never establish owned-root eligibility, including their privately compiled children. Hosting/security policy and the existing object[] closure layout are unchanged. Add controls for sibling order, outer exception regions, flags/debug mode, shared identity, and manual default/UserProvided collection. Reuse existing struct, byref, enum, nullable, quote, runtime-variable and unknown-node tests. Framework measurements against 7a871c4d, separate one-compiler processes: - Mutable capture compile: 5080 -> 4760 B (-320 B). Pre-PR e4c232d is 4376 B, so the remaining compile allocation residual is explicitly +384 B. - Activation/invoke stay 184 B, nested invocation stays 0 B. - Fresh first compile+invoke: 40272 -> 37888 B (-2384 B). - Capture8/reference/protected capture compile and runtime bytes unchanged. - All 32 modern runtime/scenario/phase allocation controls unchanged. - Descriptive two-order warm medians: mutable compile 43.92 -> 41.92 us, activation 31.80 -> 30.23 ns, nested invocation 6.064 -> 5.993 ns. Three fresh cold medians: compile+first 246.84 -> 221.64 ms. Unchanged controls show substantial host timing variation; these timing observations do not establish universal CPU parity or causal speedups. Validation: normal Standard/Light production builds all configured targets, zero warnings/errors; focused Standard/Light fixture 32/35 on Framework, 31/34 on net8 and net10, all passing; full Framework en-US runner passes 1007 TestX and 1595 legacy tests. Initial German-culture run had only existing English-message assertion failures. Independent source review found no actionable correctness defect. Raw evidence: work/pr558-repair/frame-owned-boxed.
Restore FEC's original nested-delegate slot load only when the normal root has completed capture analysis and proves owned hosting throughout without Try, Quote, runtime variables or unknown nodes. Manual/UserProvided and anonymous exception-hosted methods retain the exact verifier cast. Hosting, closure layout and delegate/Curry construction are unchanged. Against 25955bb5, four-shape one-compiler Framework probes show -32 B compile for mutable, capture8 and reference captures, warm and cold; protected capture_try and all runtime allocations are unchanged. Mutable compile is 4728 B versus pre-PR 4376 B, leaving +352 B explicitly unresolved. Two opposite process-order warm rounds and three fresh cold reps measure mutable compile 40.81 -> 36.21 us, activation 26.02 -> 24.88 ns, nested invocation 5.467 -> 5.483 ns, compile+first 185.55 -> 183.44 ms. Host timing variation in unchanged controls prevents universal CPU claims. Normal Standard/Light builds all targets: zero warnings/errors. Focused fixtures pass on Framework/net8/net10 (32/31/31 Standard, 35/34/34 Light). Full Framework en-US runner: 1007 TestX +1595 legacy passing. Independent source audit confirms the conservative owned-host guard. Evidence: work/pr558-repair/frame-owned-delegate/measurements.json and raw logs.
Omit the hidden closure cast only under the same completed ordinary owned-root proof as the nested delegate cast. Typed signatures keep their existing fast path; all anonymous/manual/UserProvided/EH/Quote/RV/unknown cases keep exact typing. No signature arrays, metadata caches, hosting or layout changes. Against 3320b13e, Framework warm/cold compilation saves 208 B for mutable, 120 B for readonly reference and 264 B for capture8; protected capture_try and runtime allocations are unchanged. Mutable compile is now 4520 B versus pre-PR 4376 (+144 B); reference is 4256 versus 4264 (-8 B). Two opposite process-order warm rounds and three fresh cold repetitions: mutable compile 42.83 -> 38.82 us, nested invocation 5.730 -> 4.963 ns, compile+first 239.07 -> 204.11 ms. Activation 25.67 -> 28.55 ns despite its unchanged emitted code illustrates host noise; no universal CPU claim. Normal Standard/Light builds all targets pass with zero warnings/errors. Focused fixtures pass on Framework/net8/net10 (32/31/31 Standard, 35/34/34 Light), including protected siblings, manual contexts and shared mutation. Combined final full suite is scheduled by the parent task. Evidence: work/pr558-repair/frame-owned-closure/measurements.json and raw logs.
Reuse the existing atomic-operand predicate for non-lifted operands. Keep complex right operands, nullable lifting, custom Light intrinsics and operator evaluation order on their existing paths. No new metadata query, cache, analysis pass or closure layout is introduced. For 64 decimal additions under real finally blocks, isolated compilation allocations fall from 11496 to 5664 B on modern .NET and 21136 to 7088 B on Framework. Warm compile improves 16-30%, compile plus first execution 12-44%, and invocation 7-19% across Standard/Light on .NET 8/10/Framework. Native fixture checks pass in all six configurations. Cold controls and material timing outliers remain in the evidence; universal parity is not established. Full combined validation follows this logical commit.
Emit non-byref try body and catch results with the existing value-parent mask before storing the typed result temporary. Receiver, lvalue and duplication flags must not cause a managed address to be stored as a struct value. Preserve enclosing EH/inlining context and genuine byref Try results; mark a loaded ordinary result as a value. Fixes the introduced Light new-struct receiver regression and existing variable/field/ref-parameter receiver forms, preserving mutation-copy semantics. Register seven native regression methods for Standard/Light on modern .NET and Framework. All six focused configurations pass40cases; modern byref-return aliases remain correct. No hosting, metadata cache, closure layout or empty-finally elimination is changed. Performance controls retain unchanged runtime/activation allocations. A genuine Framework Light compilation-history allocation residual of 192B in two capture controls remains documented; isolated controls match. This correctness repair does not claim universal performance parity. Full combined native/imported validation follows this logical commit.
Retain collision and stable-reference tests against the master implementation.
…ware methods Address dadhi review discussion_r4318926508: passing the runtime anonymous module into the module overload violates an explicit CoreCLR assertion even though tested release runtimes accept it. Remove that module-reuse workaround and its lazy holder. Use the public restricted anonymous constructor on every target; ordinary owner-hosted methods are unchanged. Keep raw/wrapped non-Exception catch matching and private-member access semantics. The supported constructor eagerly JITs at CreateDelegate, so compile-only timings must be reported separately from compile plus first execution. NonExceptionThrowPolicy, ExceptionRegionValidation and TryResultValue fixtures pass Standard/Light on net8.0, net10.0 and net472.
Resolve declared fields directly while preserving inherited/private/hidden fields and duplicate-metadata behavior. Save full construction, compilation and invocation comparisons, including per-lookup allocation reduction and the unreproduced property-test failure.
Keep semantic regression oracles from the rejected conditional-branch experiment; do not retain its inconsistent production optimization. Record 144 benchmark measurements, identical benchmark IL for kept changes, all target/native checks, and unchanged imported outcomes: 34945 pass, 152 existing failures, 36 skips, no new failures or observed crashes.
Keep alternating unused lambda signatures and earlier delegates under default, no-inlining and debug flags. The production pool return is already in master.
Call the existing terminal collector directly for parameter and constant left operands. Preserve nested-lambda capture analysis and intrinsic callbacks, while avoiding a recursive collector frame for these leaves. Emission is unchanged. Paired screening against fab2d6bd: 41 workloads, construction/compilation/invocation, Standard and Light, .NET 8 and 10, 21 samples each. Compilation allocations match for every case. Balanced256 compilation improves 2.6-6.9%; blocks32 improves 7.1-10.9%; overall workload median improves 0.6-1.0%, with mixed individual controls. Raw evidence will be retained with the current-master three-stage report. Native .NET 10: all 1718 tests pass.
Freeze master f49acef, locally merged dadhi#558 at 593c72e2, and optimized dadhi#559 source ef577910. Record 44 workloads, Standard/Light, .NET 8/10, construction/compilation/warm invocation plus a separate compilation-and-first-invocation pass. Retain 34496 main/reference samples, per-commit allocation/timing evidence, actual root and nested IL strings, source/binary hashes, rejected candidates and validation logs. Compile-only medians improve 0.7-2.2% versus dadhi#558 but remain 8.2-9.9% above master. Compilation plus first invocation remains 0.1-1.5% above master on median workload ratios. The apparent nested-exception compile-only outlier shifts JIT work into CreateDelegate for the correctness-required anonymous host; the end-to-end pass accounts for it. Keep slower System comparison cases and unchanged-code allocation controls explicit. Correct the historical IL claim: its serializer compared StringBuilder metadata. The new actual-instruction check matches all 176 root/nested bundles between dadhi#558 and dadhi#559. Production and native suites, Framework 1051 TestX plus 1601 legacy tests, and all 35064 executed imported tests pass. Existing exclusions unchanged; production source unchanged by this evidence commit.
f9fc34b to
93af41d
Compare
Reduce allocation during named LightExpression field construction and recursive collector overhead for terminal binary operands. This draft is stacked on current #558 (
dd989683), based on current upstream master (0f37356f). GitHub's nominal base remains master because the dependency branch is in the contributor fork. Review only the performance increment.Performance changes
An additional call/constructor-argument shortcut was measured but not retained because its timing benefit did not consistently reproduce. No compatibility changes from #558 are claimed as performance changes here.
Current measurements only
Fresh matched comparison: master
0f37356f, #558dd989683, #559 production source00af81b4. The #559 production source is unchanged through this report. Previous-branch reports and values have been removed.19 workloads, Standard/Light, .NET 8.0.28 / 10.0.9, four phases, two opposite-order process rounds, seven samples each: 14,896 current-stage/reference observations. CPU 5 affinity, High process priority, tiering/ReadyToRun disabled. Geometric means below give equal weight to each workload; above 1 is slower. These are descriptive ratios, not significance tests or application-throughput estimates.
Shared-host timing variation remains material. Standard construction is an unchanged System-tree control, and the measured delegates have identical IL between #558/#559. Timing movements in unchanged paths are not claimed as improvements. No universal speedup or master-parity claim is made. Compile-only costs remain above master; compile plus first invocation is much closer because exception-aware anonymous hosting can move JIT/access checks into delegate creation.
Allocations: compilation, compilation plus first invocation and warm invocation match #558 in every measured shape/configuration. Light construction reduces allocation in 6/19 shapes and matches 13/19, with no increases: about 32 B per named-field lookup, or 1,024 B in the 32-field-construction shape. One unchanged .NET 8 Standard construction control has an unexplained allocation movement; full data preserves it without attributing it to the patch.
Runtime: 76/76 actual root-plus-returned-nested instruction bundles match exactly between #558/#559. Runtime is also measured independently; no delegate execution speedup is claimed.
System: a separate unchanged reference, with no before/after columns or PR-stage delta. It is also the untimed behavior oracle. FEC is not universally faster than System; complete values are retained.
Validation and evidence
Release solution build passed; native Standard/Light .NET 8/10 runners passed (1,733 / 1,734 legacy cases plus registered fixtures); Framework passed 1,051 TestX + 1,617 legacy cases using English UI culture for existing message assertions. Imported runtime suite: 35,088 passed, 59 skipped, zero failures/crashes. Deep-tree cases remain deferred.
Current three-stage tables, all 304 result groups, standalone System values, exact IL comparison, raw samples, source/binary hashes, replay harness and full validation logs. Only current master, current #558 and final #559 are reported. #558 is unchanged by this work. Remains draft.