-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Respect JitEnableOptionalRelocs in TryReserveInitialMemory #107059
base: main
Are you sure you want to change the base?
Conversation
If you want the JitEnableOptionalRelocs=0 switch to be fully reliable, I do not think that tweaking how memory gets allocated is the right strategy. I won't ever make it fully reliable. Instead, should this switch be telling the JIT and VM to always go through jump stubs, and to disable other optimizations that depend on address proximity instead? |
Do you mean it might be still reachable even with random address? (extremely unlikely with arm64 I suppose).
including all managed-to-managed as well? won't it have a heavy impact compared to default mode? |
All these are opportunistic optimizations that can be non-deterministic, The switch documentation says that setting it to 0 should disable all of them: runtime/src/coreclr/inc/clrconfigvalues.h Lines 314 to 316 in 063ae05
It sounds like that you would like the switch to disable some of these, but not all of them. How do we decide what the switch should disable and what it should not disable? |
f7a1ad9
to
718c405
Compare
@EgorBot -arm64 --envvars DOTNET_JitEnableOptionalRelocs:0 using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
public class Bench
{
[Benchmark]
public void Test1() => Test2();
[MethodImpl(MethodImplOptions.NoInlining)] void Test2() => Test3();
[MethodImpl(MethodImplOptions.NoInlining)] void Test3() => Test4();
[MethodImpl(MethodImplOptions.NoInlining)] void Test4(){}
} |
@EgorBot -arm64 -perf --envvars DOTNET_JitEnableOptionalRelocs:0 using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
public class Bench
{
[Benchmark]
public void Test1() => Test2();
[MethodImpl(MethodImplOptions.NoInlining)] void Test2() => Test3();
[MethodImpl(MethodImplOptions.NoInlining)] void Test3() => Test4();
[MethodImpl(MethodImplOptions.NoInlining)] void Test4(){}
} |
Benchmark results on Arm64
|
Benchmark results on Arm64
Flame graphs: Main vs PR 🔥 For clean |
@EgorBot -arm64 -intel -perf --envvars DOTNET_JitEnableOptionalRelocs:0 using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
public class Bench
{
[Benchmark]
public void ManagedToManaged()
{
DoWork();
DoWork();
DoWork();
DoWork();
}
[MethodImpl(MethodImplOptions.NoInlining)] void DoWork() { }
object a;
object b;
[Benchmark]
public void WriteBarrier() => a = b;
} |
Benchmark results on Intel
Flame graphs: Main vs PR 🔥 For clean |
Ah, managed-to-managed doesn't go through a jump-stub, but rather starts doing:
if it can't do a reloc'd call (on x64) The perf impact seems to be around noise in microbenchmarks. |
@EgorBot -arm64 -perf using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
public class Bench
{
[Benchmark]
public void ManagedToManaged()
{
DoWork();
DoWork();
DoWork();
DoWork();
}
[MethodImpl(MethodImplOptions.NoInlining)] void DoWork() { }
object a;
object b;
[Benchmark]
public void WriteBarrier() => a = b;
} |
Benchmark results on Arm64
Flame graphs: Main vs PR 🔥 For clean |
Let's not try to allocate the loader heap near coreclr when
JitEnableOptionalRelocs=0
is set since it seems to be pretty random whether we successfully do that or fallback to a random memory - that leads to inconsistent performance measurements. From what I see we are more often fail to do that anyway or arm64. It also not uncommon on Linux-x64 as well.