-
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
[Perf] Linux/arm64: 2 Regressions on 12/5/2023 8:53:15 AM #96499
Comments
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsRun Information
Regressions in System.Collections.IterateFor<String>
ReproGeneral Docs link: https://github.com/dotnet/performance/blob/main/docs/benchmarking-workflow-dotnet-runtime.md git clone https://github.com/dotnet/performance.git
python3 .\performance\scripts\benchmarks_ci.py -f net8.0 --filter 'System.Collections.IterateFor<String>*' PayloadsSystem.Collections.IterateFor<String>.ImmutableArray(Size: 512)ETL FilesHistogramJIT DisasmsDocsProfiling workflow for dotnet/runtime repository Run Information
Regressions in System.Collections.IterateForEach<String>
ReproGeneral Docs link: https://github.com/dotnet/performance/blob/main/docs/benchmarking-workflow-dotnet-runtime.md git clone https://github.com/dotnet/performance.git
python3 .\performance\scripts\benchmarks_ci.py -f net8.0 --filter 'System.Collections.IterateForEach<String>*' PayloadsSystem.Collections.IterateForEach<String>.Span(Size: 512)ETL FilesHistogramJIT DisasmsDocsProfiling workflow for dotnet/runtime repository
|
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
Benchmark results on Arm64
Flame graphs: Main vs PR 🔥 For clean |
hm.. weird, looks like regression is real and is caused by #95379 but my bot failed to collect native profile + BDN failed to collect any useful info with its [DisassemblyDiagnoset] 😕 |
@EgorBot -arm64 -profiler -commit 0c513d9 vs 829524b --disasm --envvars DOTNET_JitDisasm:MySpan using BenchmarkDotNet.Attributes;
using System.Text;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
[GenericTypeArguments(typeof(string))] // reference type
public class IterateForEach<T>
{
[Params(512)]
public int Size;
private T[] _array;
[GlobalSetup(Targets = new[] { nameof(MySpan) })]
public void SetupArray() => _array = ValuesGenerator.ArrayOfUniqueValues<T>(Size);
[Benchmark]
public T MySpan()
{
T result = default;
var collection = new System.Span<T>(_array);
foreach (var item in collection)
result = item;
return result;
}
}
public static class ValuesGenerator
{
private const int Seed = 12345;
public static T[] ArrayOfUniqueValues<T>(int count)
{
if (count > 2 && typeof(T) == typeof(bool))
throw new ArgumentOutOfRangeException("count", "Cannot exceed 2 for bool values");
if (count > 255 && (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte)))
throw new ArgumentOutOfRangeException("count", "Cannot exceed 255 for byte or sbyte values");
T[] result = new T[count];
var random = new Random(Seed);
var uniqueValues = new HashSet<T>();
while (uniqueValues.Count != count)
{
T value = GenerateValue<T>(random);
if (!uniqueValues.Contains(value))
uniqueValues.Add(value);
}
uniqueValues.CopyTo(result);
return result;
}
private static T GenerateValue<T>(Random random)
{
if (typeof(T) == typeof(string))
return (T)(object)GenerateRandomString(random, 1, 50); // note: all strings have only the characters 'a'..'z', 'A'..'Z', or '0'..'9'
throw new NotImplementedException($"{typeof(T).Name} is not implemented");
}
private static string GenerateRandomString(Random random, int minLength, int maxLength)
{
var length = random.Next(minLength, maxLength);
var builder = new StringBuilder(length);
for (int i = 0; i < length; i++)
{
var rangeSelector = random.Next(0, 3);
if (rangeSelector == 0)
builder.Append((char)random.Next('a', 'z'));
else if (rangeSelector == 1)
builder.Append((char)random.Next('A', 'Z'));
else
builder.Append((char)random.Next('0', '9'));
}
return builder.ToString();
}
} |
Benchmark results on Arm64
Flame graphs: Main vs PR 🔥 For clean |
Codegen diff for hot path: https://www.diffchecker.com/mqSBe7ft/ cc @AndyAyersMS 🤷♂️ (extracted from BDN_Artifacts.zip) |
8.0 vs 9.0p6 on M1 PowerPlanMode=00000000-0000-0000-0000-000000000000 IterationTime=250ms MaxIterationCount=20
8.0 branched in August, so could be I need builds closer to the above. |
Looks like there was a big improvement on 18-Oct-23 from #93371 and the regression here on 5-Dec-23. |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
@EgorBot -arm64 -profiler -commit 0c513d9 vs 829524b using BenchmarkDotNet.Attributes;
using System.Text;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
[GenericTypeArguments(typeof(string))] // reference type
public class IterateForEach<T>
{
[Params(512)]
public int Size;
private T[] _array;
[GlobalSetup(Targets = new[] { nameof(MySpan) })]
public void SetupArray() => _array = ValuesGenerator.ArrayOfUniqueValues<T>(Size);
[Benchmark]
public T MySpan()
{
T result = default;
var collection = new System.Span<T>(_array);
foreach (var item in collection)
result = item;
return result;
}
}
public static class ValuesGenerator
{
private const int Seed = 12345;
public static T[] ArrayOfUniqueValues<T>(int count)
{
if (count > 2 && typeof(T) == typeof(bool))
throw new ArgumentOutOfRangeException("count", "Cannot exceed 2 for bool values");
if (count > 255 && (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte)))
throw new ArgumentOutOfRangeException("count", "Cannot exceed 255 for byte or sbyte values");
T[] result = new T[count];
var random = new Random(Seed);
var uniqueValues = new HashSet<T>();
while (uniqueValues.Count != count)
{
T value = GenerateValue<T>(random);
if (!uniqueValues.Contains(value))
uniqueValues.Add(value);
}
uniqueValues.CopyTo(result);
return result;
}
private static T GenerateValue<T>(Random random)
{
if (typeof(T) == typeof(string))
return (T)(object)GenerateRandomString(random, 1, 50); // note: all strings have only the characters 'a'..'z', 'A'..'Z', or '0'..'9'
throw new NotImplementedException($"{typeof(T).Name} is not implemented");
}
private static string GenerateRandomString(Random random, int minLength, int maxLength)
{
var length = random.Next(minLength, maxLength);
var builder = new StringBuilder(length);
for (int i = 0; i < length; i++)
{
var rangeSelector = random.Next(0, 3);
if (rangeSelector == 0)
builder.Append((char)random.Next('a', 'z'));
else if (rangeSelector == 1)
builder.Append((char)random.Next('A', 'Z'));
else
builder.Append((char)random.Next('0', '9'));
}
return builder.ToString();
}
} |
Benchmark results on Arm64
Flame graphs: Main vs PR 🔥 For clean |
Looks like this was fixed by #105131: |
Run Information
Regressions in System.Collections.IterateFor<String>
Test Report
Repro
General Docs link: https://github.com/dotnet/performance/blob/main/docs/benchmarking-workflow-dotnet-runtime.md
Payloads
Baseline
Compare
System.Collections.IterateFor<String>.ImmutableArray(Size: 512)
ETL Files
Histogram
JIT Disasms
Docs
Profiling workflow for dotnet/runtime repository
Benchmarking workflow for dotnet/runtime repository
Run Information
Regressions in System.Collections.IterateForEach<String>
Test Report
Repro
General Docs link: https://github.com/dotnet/performance/blob/main/docs/benchmarking-workflow-dotnet-runtime.md
Payloads
Baseline
Compare
System.Collections.IterateForEach<String>.Span(Size: 512)
ETL Files
Histogram
JIT Disasms
Docs
Profiling workflow for dotnet/runtime repository
Benchmarking workflow for dotnet/runtime repository
The text was updated successfully, but these errors were encountered: