RecyclableArrayList.AddRange added. Smaller perf improvements.

This commit is contained in:
mlemanczyk committed 2023-01-13 19:45:22 +01:00
1 parent 880abd605e
commit 012fc3b21f
8 files changed
+134 -25

No files matched your search

@@ -29,11 +29,11 @@
//public class ListVsLinkedListBenchmarks
//{
// [Benchmark]
// public void RecyclableBlockList()
// public void RecyclableArrayList()
// {
// var data = TestObjects;
// var dataCount = TestObjectCount;
// using var list = new RecyclableBlockList<object>(initialCapacity: dataCount);
// using var list = new RecyclableArrayList<object>(initialCapacity: dataCount);
// for (long i = 0; i < dataCount; i++)
// {
// list.Add(data[i]);
+3 -1
View File
@@ -5,7 +5,9 @@ using Recyclable.Collections.Benchmarks;
BenchmarkRunner.Run<RecyclableCollectionsBenchmarks>();
//var test = new RecyclableCollectionsBenchmarks();
//var benchmark = new RecyclableCollectionsBenchmarks();
//benchmark.RecyclableArrayList_Add();
//benchmark.RecyclableArrayList_Add_WithCapacity();
//BenchmarkRunner.Run<DelegateVsComparerBenchmark>();
@@ -6,28 +6,28 @@ namespace Recyclable.Collections.Benchmarks
{
private readonly List<object> _testList;
[Benchmark(Baseline = true)]
//[Benchmark(Baseline = true)]
public void List_Create()
{
var list = new List<object>();
DoNothing(list);
}
[Benchmark]
//[Benchmark]
public void List_Create_0Capacity()
{
var list = new List<object>(0);
DoNothing(list);
}
[Benchmark]
//[Benchmark]
public void List_Create_WithCapacity()
{
var list = new List<object>(TestObjectCount);
DoNothing(list);
}
//[Benchmark]
[Benchmark]
public void List_Add()
{
var data = TestObjects;
@@ -39,7 +39,7 @@ namespace Recyclable.Collections.Benchmarks
}
}
//[Benchmark]
[Benchmark(Baseline = true)]
public void List_Add_WithCapacity()
{
var data = TestObjects;
@@ -51,6 +51,23 @@ namespace Recyclable.Collections.Benchmarks
}
}
[Benchmark]
public void List_AddRange()
{
var data = TestObjects;
var list = new List<object>();
list.AddRange(data);
}
[Benchmark]
public void List_AddRange_WithCapacity()
{
var data = TestObjects;
var dataCount = TestObjectCount;
var list = new List<object>(dataCount);
list.AddRange(data);
}
//[Benchmark]
public void List_GetItem()
{
@@ -20,28 +20,28 @@ namespace Recyclable.Collections.Benchmarks
_testRecyclableList?.Dispose();
}
[Benchmark]
//[Benchmark]
public void RecyclableArrayList_Create()
{
using var list = new RecyclableArrayList<object>();
DoNothing(list);
}
[Benchmark]
//[Benchmark]
public void RecyclableArrayList_Create_0Capacity()
{
using var list = new RecyclableArrayList<object>(0);
DoNothing(list);
}
[Benchmark]
//[Benchmark]
public void RecyclableArrayList_Create_WithCapacity()
{
using var list = new RecyclableArrayList<object>(TestObjectCount);
DoNothing(list);
}
//[Benchmark]
[Benchmark]
public void RecyclableArrayList_Add()
{
var data = TestObjects;
@@ -53,7 +53,7 @@ namespace Recyclable.Collections.Benchmarks
}
}
//[Benchmark]
[Benchmark]
public void RecyclableArrayList_Add_WithCapacity()
{
var data = TestObjects;
@@ -65,6 +65,23 @@ namespace Recyclable.Collections.Benchmarks
}
}
[Benchmark]
public void RecyclableArrayList_AddRange()
{
var data = TestObjects;
using var list = new RecyclableArrayList<object>();
list.AddRange(data);
}
[Benchmark]
public void RecyclableArrayList_AddRange_WithCapacity()
{
var data = TestObjects;
var dataCount = TestObjectCount;
using var list = new RecyclableArrayList<object>(dataCount);
list.AddRange(data);
}
//[Benchmark]
public void RecyclableArrayList_GetItem()
{
@@ -6,28 +6,28 @@ namespace Recyclable.Collections.Benchmarks
{
private readonly RecyclableList<object> _testRecyclableList;
[Benchmark]
//[Benchmark]
public void RecyclableList_Create()
{
using var list = new RecyclableList<object>();
DoNothing(list);
}
[Benchmark]
//[Benchmark]
public void RecyclableList_Create_0Capacity()
{
using var list = new RecyclableList<object>(totalItemsCount: 0);
DoNothing(list);
}
[Benchmark]
//[Benchmark]
public void RecyclableList_Create_WithCapacity()
{
using var list = new RecyclableList<object>(totalItemsCount: TestObjectCount);
DoNothing(list);
}
//[Benchmark]
[Benchmark]
public void RecyclableList_Add()
{
var data = TestObjects;
@@ -39,7 +39,7 @@ namespace Recyclable.Collections.Benchmarks
}
}
//[Benchmark]
[Benchmark]
public void RecyclableList_Add_WithCapacity()
{
var data = TestObjects;
+45 -6
View File
@@ -1,4 +1,5 @@
using System.Collections;
using System.Buffers;
using System.Collections;
namespace Recyclable.Collections
{
@@ -36,7 +37,7 @@ namespace Recyclable.Collections
}
}
protected void EnsureCapacity(in int requestedCapacity)
protected ref int EnsureCapacity(in int requestedCapacity)
{
int newCapacity;
switch (_capacity > 0)
@@ -56,7 +57,9 @@ namespace Recyclable.Collections
}
_memory = SetNewLength(_memory, newCapacity);
_capacity = _memory.Length;
newCapacity = _memory.Length;
_capacity = newCapacity;
return ref _capacity;
}
#pragma warning disable CS8618 // _memory will be initialized when the 1st item is added
@@ -107,6 +110,7 @@ namespace Recyclable.Collections
}
}
}
public int Count { get; set; }
public bool IsReadOnly { get; } = false;
@@ -115,13 +119,48 @@ namespace Recyclable.Collections
int requestedCapacity = Count + 1;
if (_capacity < requestedCapacity)
{
EnsureCapacity(requestedCapacity);
_ = EnsureCapacity(requestedCapacity);
}
_memory[Count] = item;
Count++;
}
public void AddRange(in T[] items)
{
int sourceItemsCount = items.Length;
int targetCapacity = Count + sourceItemsCount;
if (_capacity < targetCapacity)
{
_ = EnsureCapacity(targetCapacity);
}
Span<T> itemsSpan = items.AsSpan();
for (int sourceItemIdx = 0, targetItemIdx = Count; sourceItemIdx < sourceItemsCount;)
{
_memory[targetItemIdx++] = itemsSpan[sourceItemIdx++];
}
Count = targetCapacity;
}
public void AddRange(in List<T> items)
{
var sourceItemsCount = items.Count;
var targetCapacity = Count + sourceItemsCount;
if (_capacity < targetCapacity)
{
_ = EnsureCapacity(targetCapacity);
}
for (int sourceItemIdx = 0, targetItemIdx = Count; sourceItemIdx < sourceItemsCount;)
{
_memory[targetItemIdx++] = items[sourceItemIdx++];
}
Count = targetCapacity;
}
public void Clear()
{
Count = 0;
@@ -159,9 +198,9 @@ namespace Recyclable.Collections
public void Insert(int index, T item)
{
int requestedCapacity = Count + 1;
if (Capacity < requestedCapacity)
if (_capacity < requestedCapacity)
{
EnsureCapacity(requestedCapacity);
_ = EnsureCapacity(requestedCapacity);
}
for (var toMoveIdx = Count - 1; toMoveIdx >= index; toMoveIdx--)
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@@ -6,7 +6,7 @@ namespace Recyclable.CollectionsTests
public class RecyclableArrayListTests
{
private readonly static IEnumerable<int> _testData = Enumerable.Range(1, 20);
[Fact]
public void AddCountShouldSucceed()
{
@@ -28,6 +28,40 @@ namespace Recyclable.CollectionsTests
.And.BeEquivalentTo(testData);
}
[Fact]
public void AddRangeShouldAddItemsInCorrectOrderWhenSourceIsArray()
{
// Prepare
var testData = _testData.ToArray();
var list = new RecyclableArrayList<int>();
// Act
list.AddRange(testData);
// Validate
_ = list.Capacity.Should().Be(20, "when capacity == 0, then we allocate as much memory as needed, only");
_ = list.Should().HaveCount(testData.Length)
.And.ContainInConsecutiveOrder(testData)
.And.BeEquivalentTo(testData);
}
[Fact]
public void AddRangeShouldAddItemsInCorrectOrderWhenSourceIsList()
{
// Prepare
var testData = _testData.ToList();
var list = new RecyclableArrayList<int>();
// Act
list.AddRange(testData);
// Validate
_ = list.Capacity.Should().Be(20, "when capacity == 0, then we allocate as much memory as needed, only");
_ = list.Should().HaveCount(testData.Count)
.And.ContainInConsecutiveOrder(testData)
.And.BeEquivalentTo(testData);
}
[Fact]
public void InsertAtTheBeginningShouldMoveItems()
{