Skip to content

Commit

Permalink
Add BenchSort to readme
Browse files Browse the repository at this point in the history
  • Loading branch information
xoofx committed Oct 27, 2024
1 parent c2c2229 commit f1bbe1e
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 1 deletion.
19 changes: 18 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ The code has been derived from the .NET Core runtime released under the MIT lice
- Proper debugger support for collections with custom `DebuggerDisplay`
- A few advanced unsafe methods to avoid checks
- e.g `Unsafe<T>.UnsafeSetCount`, `Unsafe<T>.UnsafeGetRefAt`...
- NativeAOT compatible
- A fast sort by ref via `Span<T>.SortByRef` that can inline the comparer and avoid the copy to the stack of the value being compared.
- - NativeAOT compatible
- `net8.0`+ support

## 📖 Usage
Expand Down Expand Up @@ -100,6 +101,7 @@ Some benchmarks are available in the `src\XenoAtom.Collections.Bench` folder. He

- `UnsafeList<T>` and `UnsafeDictionary<TKey, TValue>` can be up to 20% faster than the standard `List<T>` and `Dictionary<TKey, TValue>` for some scenarios.
- `UnsafeList<T>.N16` can be up to 50% faster than the standard `List<T>` for adding elements.
- `Span<T>.SortByRef` can be up to 50% faster than `Array.Sort`/`Span.Sort` for some scenarios.


| Method | Mean | Error | StdDev | Ratio |
Expand All @@ -115,6 +117,21 @@ Some benchmarks are available in the `src\XenoAtom.Collections.Bench` folder. He
| `Dictionary<int, int>` | 55.06 ns | 0.307 ns | 0.287 ns | 1.00 |


| Method | ParamSize | Mean | Error | StdDev | Ratio | Gen0 | Allocated | Alloc Ratio |
|---------- |---------- |-------------:|----------:|----------:|------:|-------:|----------:|------------:|
| SortByRef | 3 | 6.468 ns | 0.0631 ns | 0.0590 ns | 0.43 | - | - | 0.00 |
| Sort | 3 | 14.993 ns | 0.0419 ns | 0.0350 ns | 1.00 | 0.0038 | 64 B | 1.00 |
| | | | | | | | | |
| SortByRef | 8 | 30.392 ns | 0.1365 ns | 0.1277 ns | 0.75 | - | - | 0.00 |
| Sort | 8 | 40.525 ns | 0.1555 ns | 0.1379 ns | 1.00 | 0.0038 | 64 B | 1.00 |
| | | | | | | | | |
| SortByRef | 16 | 73.797 ns | 0.1232 ns | 0.1092 ns | 0.59 | - | - | 0.00 |
| Sort | 16 | 125.879 ns | 0.5184 ns | 0.4849 ns | 1.00 | 0.0038 | 64 B | 1.00 |
| | | | | | | | | |
| SortByRef | 256 | 870.983 ns | 1.4083 ns | 1.0995 ns | 0.48 | - | - | 0.00 |
| Sort | 256 | 1,813.291 ns | 8.7028 ns | 8.1406 ns | 1.00 | 0.0038 | 64 B | 1.00 |



## 🪪 License

Expand Down
74 changes: 74 additions & 0 deletions src/XenoAtom.Collections.Bench/BenchSort.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// Licensed under the BSD-Clause 2 license.
// See license.txt file in the project root for full license information.

using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using XenoAtom.Collections;

namespace XenoAtom.Collections.Bench;

[MemoryDiagnoser]
public class BenchSort
{
private Item[] _data;
private Item[] _copy;

public BenchSort()
{
_data = Array.Empty<Item>();
}

public Item[] Data => _data;

[Params(3, 8, 16, 256)]
public int ParamSize { get; set; }

[GlobalSetup]
public void Setup()
{
_data = Enumerable.Range(0, ParamSize).Select(i => new Item(1024.0f - i, i)).ToArray();
_copy = _data.ToArray();
}

[Benchmark]
public void SortByRef()
{
_copy.AsSpan().CopyTo(_data);
_data.AsSpan().SortByRef(new ItemComparerByRef());
}

[Benchmark(Baseline = true)]
public void Sort()
{
_copy.AsSpan().CopyTo(_data);
_data.AsSpan().Sort(ItemComparer.Instance);
}

public struct Item
{
public Item(float priority, int index)
{
Priority = priority;
Index = index;
}

public float Priority;
public int Index;
public int NotUsed1;
public int NotUsed2;
}

private class ItemComparer : IComparer<Item>
{
public static readonly ItemComparer Instance = new ItemComparer();

public int Compare(Item x, Item y) => x.Priority.CompareTo(y.Priority);
}

private readonly struct ItemComparerByRef : IComparerByRef<Item>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool LessThan(in Item left, in Item right) => left.Priority < right.Priority;
}
}

0 comments on commit f1bbe1e

Please sign in to comment.