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
+133 -24

No files matched your search

@@ -29,11 +29,11 @@
//public class ListVsLinkedListBenchmarks //public class ListVsLinkedListBenchmarks
//{ //{
// [Benchmark] // [Benchmark]
// public void RecyclableBlockList() // public void RecyclableArrayList()
// { // {
// var data = TestObjects; // var data = TestObjects;
// var dataCount = TestObjectCount; // 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++) // for (long i = 0; i < dataCount; i++)
// { // {
// list.Add(data[i]); // list.Add(data[i]);
+3 -1
View File
@@ -5,7 +5,9 @@ using Recyclable.Collections.Benchmarks;
BenchmarkRunner.Run<RecyclableCollectionsBenchmarks>(); BenchmarkRunner.Run<RecyclableCollectionsBenchmarks>();
//var test = new RecyclableCollectionsBenchmarks(); //var benchmark = new RecyclableCollectionsBenchmarks();
//benchmark.RecyclableArrayList_Add();
//benchmark.RecyclableArrayList_Add_WithCapacity();
//BenchmarkRunner.Run<DelegateVsComparerBenchmark>(); //BenchmarkRunner.Run<DelegateVsComparerBenchmark>();
@@ -6,28 +6,28 @@ namespace Recyclable.Collections.Benchmarks
{ {
private readonly List<object> _testList; private readonly List<object> _testList;
[Benchmark(Baseline = true)] //[Benchmark(Baseline = true)]
public void List_Create() public void List_Create()
{ {
var list = new List<object>(); var list = new List<object>();
DoNothing(list); DoNothing(list);
} }
[Benchmark] //[Benchmark]
public void List_Create_0Capacity() public void List_Create_0Capacity()
{ {
var list = new List<object>(0); var list = new List<object>(0);
DoNothing(list); DoNothing(list);
} }
[Benchmark] //[Benchmark]
public void List_Create_WithCapacity() public void List_Create_WithCapacity()
{ {
var list = new List<object>(TestObjectCount); var list = new List<object>(TestObjectCount);
DoNothing(list); DoNothing(list);
} }
//[Benchmark] [Benchmark]
public void List_Add() public void List_Add()
{ {
var data = TestObjects; var data = TestObjects;
@@ -39,7 +39,7 @@ namespace Recyclable.Collections.Benchmarks
} }
} }
//[Benchmark] [Benchmark(Baseline = true)]
public void List_Add_WithCapacity() public void List_Add_WithCapacity()
{ {
var data = TestObjects; 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] //[Benchmark]
public void List_GetItem() public void List_GetItem()
{ {
@@ -20,28 +20,28 @@ namespace Recyclable.Collections.Benchmarks
_testRecyclableList?.Dispose(); _testRecyclableList?.Dispose();
} }
[Benchmark] //[Benchmark]
public void RecyclableArrayList_Create() public void RecyclableArrayList_Create()
{ {
using var list = new RecyclableArrayList<object>(); using var list = new RecyclableArrayList<object>();
DoNothing(list); DoNothing(list);
} }
[Benchmark] //[Benchmark]
public void RecyclableArrayList_Create_0Capacity() public void RecyclableArrayList_Create_0Capacity()
{ {
using var list = new RecyclableArrayList<object>(0); using var list = new RecyclableArrayList<object>(0);
DoNothing(list); DoNothing(list);
} }
[Benchmark] //[Benchmark]
public void RecyclableArrayList_Create_WithCapacity() public void RecyclableArrayList_Create_WithCapacity()
{ {
using var list = new RecyclableArrayList<object>(TestObjectCount); using var list = new RecyclableArrayList<object>(TestObjectCount);
DoNothing(list); DoNothing(list);
} }
//[Benchmark] [Benchmark]
public void RecyclableArrayList_Add() public void RecyclableArrayList_Add()
{ {
var data = TestObjects; var data = TestObjects;
@@ -53,7 +53,7 @@ namespace Recyclable.Collections.Benchmarks
} }
} }
//[Benchmark] [Benchmark]
public void RecyclableArrayList_Add_WithCapacity() public void RecyclableArrayList_Add_WithCapacity()
{ {
var data = TestObjects; 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] //[Benchmark]
public void RecyclableArrayList_GetItem() public void RecyclableArrayList_GetItem()
{ {
@@ -6,28 +6,28 @@ namespace Recyclable.Collections.Benchmarks
{ {
private readonly RecyclableList<object> _testRecyclableList; private readonly RecyclableList<object> _testRecyclableList;
[Benchmark] //[Benchmark]
public void RecyclableList_Create() public void RecyclableList_Create()
{ {
using var list = new RecyclableList<object>(); using var list = new RecyclableList<object>();
DoNothing(list); DoNothing(list);
} }
[Benchmark] //[Benchmark]
public void RecyclableList_Create_0Capacity() public void RecyclableList_Create_0Capacity()
{ {
using var list = new RecyclableList<object>(totalItemsCount: 0); using var list = new RecyclableList<object>(totalItemsCount: 0);
DoNothing(list); DoNothing(list);
} }
[Benchmark] //[Benchmark]
public void RecyclableList_Create_WithCapacity() public void RecyclableList_Create_WithCapacity()
{ {
using var list = new RecyclableList<object>(totalItemsCount: TestObjectCount); using var list = new RecyclableList<object>(totalItemsCount: TestObjectCount);
DoNothing(list); DoNothing(list);
} }
//[Benchmark] [Benchmark]
public void RecyclableList_Add() public void RecyclableList_Add()
{ {
var data = TestObjects; var data = TestObjects;
@@ -39,7 +39,7 @@ namespace Recyclable.Collections.Benchmarks
} }
} }
//[Benchmark] [Benchmark]
public void RecyclableList_Add_WithCapacity() public void RecyclableList_Add_WithCapacity()
{ {
var data = TestObjects; var data = TestObjects;
+45 -6
View File
@@ -1,4 +1,5 @@
using System.Collections; using System.Buffers;
using System.Collections;
namespace Recyclable.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; int newCapacity;
switch (_capacity > 0) switch (_capacity > 0)
@@ -56,7 +57,9 @@ namespace Recyclable.Collections
} }
_memory = SetNewLength(_memory, newCapacity); _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 #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 int Count { get; set; }
public bool IsReadOnly { get; } = false; public bool IsReadOnly { get; } = false;
@@ -115,13 +119,48 @@ namespace Recyclable.Collections
int requestedCapacity = Count + 1; int requestedCapacity = Count + 1;
if (_capacity < requestedCapacity) if (_capacity < requestedCapacity)
{ {
EnsureCapacity(requestedCapacity); _ = EnsureCapacity(requestedCapacity);
} }
_memory[Count] = item; _memory[Count] = item;
Count++; 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() public void Clear()
{ {
Count = 0; Count = 0;
@@ -159,9 +198,9 @@ namespace Recyclable.Collections
public void Insert(int index, T item) public void Insert(int index, T item)
{ {
int requestedCapacity = Count + 1; int requestedCapacity = Count + 1;
if (Capacity < requestedCapacity) if (_capacity < requestedCapacity)
{ {
EnsureCapacity(requestedCapacity); _ = EnsureCapacity(requestedCapacity);
} }
for (var toMoveIdx = Count - 1; toMoveIdx >= index; toMoveIdx--) for (var toMoveIdx = Count - 1; toMoveIdx >= index; toMoveIdx--)
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@@ -28,6 +28,40 @@ namespace Recyclable.CollectionsTests
.And.BeEquivalentTo(testData); .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] [Fact]
public void InsertAtTheBeginningShouldMoveItems() public void InsertAtTheBeginningShouldMoveItems()
{ {