Skip to content

Inefficient codegen when a lambda references an instance member #40009

Description

@smoogipoo

Description

We've recently encountered a method allocating even though there was no allocate-y code running. We've since tracked this down to the following:

IL shows the capturing lambda's DisplayClass always seems to be "allocated" as soon as the method is entered, but the JIT has the ability to control when the object is initialised. When the lambda captures both a local and this, the JIT is suddenly unable to forego this initialisation even if the method terminates execution early.

Here's a gist that shows the issue: https://gist.github.com/smoogipoo/810c033962b8a95289dbdabd9d84801b
And a SharpLab repro.

Is this a valid and/or known issue, or something we should be wary of going forward?

Configuration + Data

BenchmarkDotNet=v0.12.1, OS=manjaro 
AMD Ryzen 9 3950X, 1 CPU, 32 logical and 16 physical cores
.NET Core SDK=3.1.103
  [Host]        : .NET Core 2.2.8 (CoreCLR 4.6.28207.03, CoreFX 4.6.28208.02), X64 RyuJIT
  .NET Core 2.2 : .NET Core 2.2.8 (CoreCLR 4.6.28207.03, CoreFX 4.6.28208.02), X64 RyuJIT
  .NET Core 3.1 : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
Method Job Runtime Mean Error StdDev Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated
SafeMethod .NET Core 2.2 .NET Core 2.2 545.8 ns 0.47 ns 0.41 ns 1.00 0.00 - - - -
AllocatingMethod .NET Core 2.2 .NET Core 2.2 7,151.4 ns 135.02 ns 112.75 ns 13.10 0.20 24.4064 - - 32000 B
SafeMethod .NET Core 3.1 .NET Core 3.1 276.8 ns 0.26 ns 0.23 ns 1.00 0.00 - - - -
AllocatingMethod .NET Core 3.1 .NET Core 3.1 9,072.8 ns 179.96 ns 438.05 ns 32.64 1.40 0.9460 - - 32000 B

I've also run this on mono, which seems to always initialise the object (see Gen 0, Benchmark.Net doesn't seem to have allocation tracking on mono).

BenchmarkDotNet=v0.12.1, OS=manjaro
AMD Ryzen 9 3950X, 1 CPU, 32 logical and 16 physical cores
  [Host]     : Mono 6.4.0 (makepkg/fe64a4765e6 Sat), X64
  Job-CKTNGU : Mono 6.4.0 (makepkg/fe64a4765e6 Sat), X64

Runtime=Mono
Method Mean Error StdDev Ratio Gen 0 Gen 1 Gen 2 Allocated
SafeMethod 4.491 us 0.0069 us 0.0054 us 1.00 5.7449 - - -
AllocatingMethod 5.031 us 0.0076 us 0.0064 us 1.12 7.6904 - - -

category:cq
theme:dead-code
skill-level:expert
cost:medium

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions