Skip to content

Commit 99a6283

Browse files
committed
Optimized ArrayBuilder
1 parent 4fdddc4 commit 99a6283

File tree

1 file changed

+51
-30
lines changed

1 file changed

+51
-30
lines changed

src/ImageSharp.Drawing/Shapes/PolygonClipper/ArrayBuilder{T}.cs

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4+
using System.Diagnostics.CodeAnalysis;
45
using System.Runtime.CompilerServices;
56

67
namespace SixLabors.ImageSharp.Drawing.Shapes.PolygonClipper;
@@ -13,7 +14,6 @@ internal struct ArrayBuilder<T>
1314
where T : struct
1415
{
1516
private const int DefaultCapacity = 4;
16-
private const int MaxCoreClrArrayLength = 0x7FeFFFFF;
1717

1818
// Starts out null, initialized on first Add.
1919
private T[]? data;
@@ -41,17 +41,14 @@ public int Length
4141

4242
set
4343
{
44-
if (value != this.size)
44+
if (value > 0)
4545
{
46-
if (value > 0)
47-
{
48-
this.EnsureCapacity(value);
49-
this.size = value;
50-
}
51-
else
52-
{
53-
this.size = 0;
54-
}
46+
this.EnsureCapacity(value);
47+
this.size = value;
48+
}
49+
else
50+
{
51+
this.size = 0;
5552
}
5653
}
5754
}
@@ -81,10 +78,27 @@ public readonly ref T this[int index]
8178
public void Add(T item)
8279
{
8380
int position = this.size;
81+
T[]? array = this.data;
8482

85-
// Expand the array.
86-
this.Length++;
87-
this.data![position] = item;
83+
if (array != null && (uint)position < (uint)array.Length)
84+
{
85+
this.size = position + 1;
86+
array[position] = item;
87+
}
88+
else
89+
{
90+
this.AddWithResize(item);
91+
}
92+
}
93+
94+
// Non-inline from Add to improve its code quality as uncommon path
95+
[MethodImpl(MethodImplOptions.NoInlining)]
96+
private void AddWithResize(T item)
97+
{
98+
int size = this.size;
99+
this.Grow(size + 1);
100+
this.size = size + 1;
101+
this.data[size] = item;
88102
}
89103

90104
/// <summary>
@@ -110,26 +124,33 @@ private void EnsureCapacity(int min)
110124
int length = this.data?.Length ?? 0;
111125
if (length < min)
112126
{
113-
// Same expansion algorithm as List<T>.
114-
uint newCapacity = length == 0 ? DefaultCapacity : (uint)length * 2u;
115-
if (newCapacity > MaxCoreClrArrayLength)
116-
{
117-
newCapacity = MaxCoreClrArrayLength;
118-
}
127+
this.Grow(min);
128+
}
129+
}
119130

120-
if (newCapacity < min)
121-
{
122-
newCapacity = (uint)min;
123-
}
131+
[MemberNotNull(nameof(this.data))]
132+
private void Grow(int capacity)
133+
{
134+
// Same expansion algorithm as List<T>.
135+
int length = this.data?.Length ?? 0;
136+
int newCapacity = length == 0 ? DefaultCapacity : length * 2;
137+
if ((uint)newCapacity > Array.MaxLength)
138+
{
139+
newCapacity = Array.MaxLength;
140+
}
124141

125-
T[] array = new T[newCapacity];
142+
if (newCapacity < capacity)
143+
{
144+
newCapacity = capacity;
145+
}
126146

127-
if (this.size > 0)
128-
{
129-
Array.Copy(this.data!, array, this.size);
130-
}
147+
T[] array = new T[newCapacity];
131148

132-
this.data = array;
149+
if (this.size > 0)
150+
{
151+
Array.Copy(this.data!, array, this.size);
133152
}
153+
154+
this.data = array;
134155
}
135156
}

0 commit comments

Comments
 (0)