Nonbreaking performance tweaks (#17106)
* Avoid doing multiple lookups in dictionaries, avoid doing string interpolation & adding single char strings to a StringBuilder, made some private/internal classes & some private methods static when possible, use FrozenSet for InvalidFileNameChars
* Avoid some array + list allocations & async methods and made some private methods static
* Avoid double lookup of XML attribute (and double null check) & avoid an unneeded lookup before writing to a dictionary
* Avoid some double lookups
# Conflicts:
# src/Umbraco.Core/Services/LocalizedTextService.cs
* Avoid double lookups
# Conflicts:
# src/Umbraco.Core/Services/LocalizedTextService.cs
* Avoid double lookups
* List AsSpan, also to trigger a new build that hopefully goes through
* Avoid concatting strings when using writer & more static
* Updated CollectionBenchmarks to show that ToArray isn't always the fastest & Lists can be iterated nearly as fast as arrays (and that ToList is nearly as fast as ToArray on IReadOnlyLists in .NET 8)
* Fix rebase
* Use explicit types ❤️ (I thought it was the other way round...)
# Conflicts:
# src/Umbraco.Core/Services/LocalizedTextService.cs
* Reduce number of lines in HtmlStringUtilities.Truncate to pass code quality analysis
* Avoid double lookups & allocating empty arrays
* Use native List Find instead of LINQ
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
@@ -7,20 +6,42 @@ namespace Umbraco.Tests.Benchmarks
|
||||
[MemoryDiagnoser]
|
||||
public class CollectionBenchmarks
|
||||
{
|
||||
private static readonly IEnumerable<int> _enumerable = Enumerable.Range(0, 1000);
|
||||
private static readonly int[] _array = _enumerable.ToArray();
|
||||
private static readonly List<int> _list = _enumerable.ToList();
|
||||
private const int Size = 1000;
|
||||
private static readonly IEnumerable<int> _IReadOnlyListEnumerable = Enumerable.Range(0, Size);
|
||||
private static readonly int[] _array = _IReadOnlyListEnumerable.ToArray();
|
||||
private static readonly List<int> _list = _IReadOnlyListEnumerable.ToList();
|
||||
|
||||
[Benchmark]
|
||||
public int[] ToArray()
|
||||
public int[] IReadOnlyListToArray()
|
||||
{
|
||||
return _enumerable.ToArray();
|
||||
return _IReadOnlyListEnumerable.ToArray();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public List<int> ToList()
|
||||
public List<int> IReadOnlyListToList()
|
||||
{
|
||||
return _enumerable.ToList();
|
||||
return _IReadOnlyListEnumerable.ToList();
|
||||
}
|
||||
|
||||
// LINQ Where and many other enumerables does not know how many items there will be returned
|
||||
private static IEnumerable<int> YieldingEnumerable()
|
||||
{
|
||||
for (int i = 0; i < Size; i++)
|
||||
{
|
||||
yield return i;
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int[] YieldingEnumerableToArray()
|
||||
{
|
||||
return YieldingEnumerable().ToArray();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public List<int> YieldingEnumerableToList()
|
||||
{
|
||||
return YieldingEnumerable().ToList();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
@@ -32,6 +53,14 @@ namespace Umbraco.Tests.Benchmarks
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void IterateAsSpanList()
|
||||
{
|
||||
foreach (int item in CollectionsMarshal.AsSpan(_list))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void IterateList()
|
||||
{
|
||||
@@ -40,18 +69,21 @@ namespace Umbraco.Tests.Benchmarks
|
||||
}
|
||||
}
|
||||
|
||||
//BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19044.2006 (21H2)
|
||||
//Intel Core i9-10885H CPU 2.40GHz, 1 CPU, 16 logical and 8 physical cores
|
||||
//.NET SDK= 6.0.401
|
||||
// [Host] : .NET 6.0.9 (6.0.922.41905), X64 RyuJIT
|
||||
// DefaultJob : .NET 6.0.9 (6.0.922.41905), X64 RyuJIT
|
||||
//BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3)
|
||||
//Intel Core i7-10750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
|
||||
//.NET SDK 8.0.401
|
||||
// [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2
|
||||
// DefaultJob : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2
|
||||
//
|
||||
//
|
||||
//| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Allocated |
|
||||
//|------------- |-----------:|---------:|---------:|-------:|-------:|----------:|
|
||||
//| ToArray | 503.8 ns | 5.11 ns | 4.53 ns | 0.4807 | 0.0067 | 4,024 B |
|
||||
//| ToList | 1,369.0 ns | 25.38 ns | 49.50 ns | 0.4845 | 0.0134 | 4,056 B |
|
||||
//| IterateArray | 244.9 ns | 3.29 ns | 2.75 ns | - | - | - |
|
||||
//| IterateList | 620.5 ns | 4.45 ns | 3.95 ns | - | - | - |
|
||||
//| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|
||||
//|-------------------------- |-----------:|---------:|---------:|-------:|-------:|----------:|
|
||||
//| IReadOnlyListToArray | 227.2 ns | 4.35 ns | 4.46 ns | 0.6413 | - | 4024 B |
|
||||
//| IReadOnlyListToList | 236.8 ns | 3.77 ns | 3.53 ns | 0.6464 | 0.0098 | 4056 B |
|
||||
//| YieldingEnumerableToArray | 3,249.0 ns | 63.49 ns | 96.96 ns | 1.3580 | 0.0114 | 8528 B |
|
||||
//| YieldingEnumerableToList | 2,791.3 ns | 54.36 ns | 76.21 ns | 1.3466 | 0.0229 | 8456 B |
|
||||
//| IterateArray | 245.3 ns | 4.09 ns | 3.42 ns | - | - | - |
|
||||
//| IterateAsSpanList | 249.9 ns | 3.10 ns | 2.90 ns | - | - | - |
|
||||
//| IterateList | 543.2 ns | 10.86 ns | 17.84 ns | - | - | - |
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user