runtime icon indicating copy to clipboard operation
runtime copied to clipboard

Expression.Compile performance regression on .NET7 RC1

Open KeterSCP opened this issue 3 years ago • 4 comments

Description

Running simple benchmark to test performance of Expression.Compile shows regressions on .NET7 RC1

Benchmark code
using System;
using System.Linq.Expressions;

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;

BenchmarkRunner.Run<Benchmarks>();

[MemoryDiagnoser(false)]
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net70)]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByJob)]
public class Benchmarks
{
  private static readonly Expression<Func<MyClass>> _factory = FactoryCreator<MyClass>.GetFactory();

  [Benchmark]
  public Func<MyClass> CompileFactory()
  {
      return _factory.Compile();
  }
}

public static class FactoryCreator<T>
{
  public static Expression<Func<T>> GetFactory()
  {
      var ctorBody = Expression.New(typeof(T).GetConstructor(Type.EmptyTypes)!);

      return Expression.Lambda<Func<T>>(ctorBody);
  }
}

public class MyClass {}

Regression?

Yes. On .NET 6 this is ~50% faster

Data


BenchmarkDotNet=v0.13.2, OS=Windows 11 (10.0.22000.978/21H2)
AMD Ryzen 5 3600, 1 CPU, 12 logical and 6 physical cores
.NET SDK=7.0.100-rc.1.22431.12
  [Host]   : .NET 7.0.0 (7.0.22.42610), X64 RyuJIT AVX2
  .NET 6.0 : .NET 6.0.9 (6.0.922.41905), X64 RyuJIT AVX2
  .NET 7.0 : .NET 7.0.0 (7.0.22.42610), X64 RyuJIT AVX2


Method Job Runtime Mean Error StdDev Allocated
CompileFactory .NET 6.0 .NET 6.0 33.51 μs 0.361 μs 0.337 μs 3.66 KB
CompileFactory .NET 7.0 .NET 7.0 51.86 μs 0.223 μs 0.208 μs 3.69 KB

KeterSCP avatar Sep 20 '22 13:09 KeterSCP

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

Reproduces on RC1 but doesn't reproduce on Main

EgorBo avatar Sep 20 '22 14:09 EgorBo

@EgorBo does it mean that in the final .NET7 release this will be fixed? If so I can close the issue

KeterSCP avatar Sep 20 '22 14:09 KeterSCP

@EgorBo does it mean that in the final .NET7 release this will be fixed? If so I can close the issue

No, Main is .NET8, we need to check this on the latest .NET 7.0 daily build Perhaps this issue rings a bell to anyone? It seems to be in either coreclr.dll or clrjit.dll (I replaced those in net7.0 by net8.0 binaries and got the results back)

EgorBo avatar Sep 20 '22 14:09 EgorBo

Can you try the benchmark with COMPlus_EnableWriteXorExecute=0? We have a fix for a similar situation in RC2

cc @mangod9

jeffschwMSFT avatar Sep 21 '22 14:09 jeffschwMSFT

Can you try the benchmark with COMPlus_EnableWriteXorExecute=0?

Yes, I can confirm disabling W^X fixes the regression:

Method Job EnvironmentVariables Runtime Mean Error StdDev
CompileFactory .NET 6 Empty .NET 6.0 34.92 μs 0.319 μs 0.283 μs
CompileFactory .NET 7 Empty .NET 7.0 51.46 μs 0.338 μs 0.316 μs
CompileFactory .NET 7 with W^X disabled COMPlus_EnableWriteXorExecute=0 .NET 7.0 28.20 μs 0.231 μs 0.216 μs

Feel free to close the issue if it will be fixed in the RC2

KeterSCP avatar Sep 21 '22 14:09 KeterSCP

It would be good to validate with RC2. The fix we have in RC2 is to cache the W^X mapping, so rapid use of pages (like this micro benchmark) should notice a benefit.

jeffschwMSFT avatar Sep 21 '22 15:09 jeffschwMSFT

marking for 7 for now till we confirm its fixed in RC2. @KeterSCP can you please try a build from rc2 installer repo: https://github.com/dotnet/installer/tree/release/7.0.1xx

mangod9 avatar Sep 21 '22 15:09 mangod9

@mangod9 could you please tell me how can I try the RC2 build? should I build it from source or there are already built installers?

KeterSCP avatar Sep 21 '22 16:09 KeterSCP

yeah you can use the installer link listed here: https://github.com/dotnet/installer/tree/release/7.0.1xx#table. Just note that daily builds are not signed

mangod9 avatar Sep 21 '22 16:09 mangod9

Thanks for the tip @mangod9! I can confirm that regression was fixed on the latest .NET7 build:

Method Job EnvironmentVariables Mean Error StdDev Allocated
CompileFactory .NET 7 Empty 32.61 μs 0.247 μs 0.231 μs 3.69 KB
CompileFactory .NET 7 with disabled W^X COMPlus_EnableWriteXorExecute=0 30.67 μs 0.325 μs 0.304 μs 3.69 KB

KeterSCP avatar Sep 21 '22 16:09 KeterSCP

Thanks for confirming @KeterSCP. Closing this issue then.

mangod9 avatar Sep 21 '22 20:09 mangod9