Skip to content

ValueTupleCompareCached microbenchmark slow in ios-like configuration #123622

@BrzVlad

Description

@BrzVlad

This benchmark is around 200x slower when running in ios-like configuration (composite r2r + interp fallback) on desktop, compared to default (jit).

Interestingly enough, after profiling, it turns out that most of the time spent is not in interpreting methods but rather in R2R machinery. In order to reproduce, the application was compiled with composite-r2r. The minimal runtime configuration diff that reproduces this issue is BrzVlad@3a4d118. At runtime, tiering has to be disabled as well (DOTNET_TieredCompilation=0).

Most of the time spent originates in ExternalMethodFixupWorker, which is called for every benchmark iteration, suggesting that a callsite from r2r is not properly patched. The runtime seems to attempt to resolve the call for each microbenchmark iteration, with excessive time spent related to signature decoding. Attached a profile showing the amount of time spent in the hottest methods.

Image

Even when running with composite-r2r with jit fallback, the benchmark was still 50x slower than normal jit, with the above runtime configuration. Microbenchmark extracted from https://github.com/dotnet/performance/blob/main/src/benchmarks/micro/runtime/Devirtualization/DefaultEqualityComparerPerf.cs#L79

using System;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System.Globalization;

public class EqualityComparerFixture<T> where T : IEquatable<T>
{
	IEqualityComparer<T> comparer;

	public EqualityComparerFixture()
	{
		comparer = EqualityComparer<T>.Default;
	}

	[MethodImpl(MethodImplOptions.NoInlining)]
	public bool CompareCached(ref T a, ref T b)
	{
		return comparer.Equals(a, b);
	}
}

public class Program {

	public enum E {
		RED = 1,
		BLUE = 2
	}

	private EqualityComparerFixture<ValueTuple<byte, E, int>> valueTupleFixture = new EqualityComparerFixture<ValueTuple<byte, E, int>>();
	private ValueTuple<byte, E, int> v0 = new ValueTuple<byte, E, int>(3, E.RED, 11);

	public bool ValueTupleCompareCached() => valueTupleFixture.CompareCached(ref v0, ref v0);

	public void BenchCompareTuple()
	{
		for (int j = 0; j < 100000000; j++)
			ValueTupleCompareCached();
		Console.WriteLine ("Benchmarked compare tuple");
	}

	public static void Main(string[] args)
	{
		Program p = new Program();
		p.BenchCompareTuple();
	}
}

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions