Skip to content

Commit aaaf9a8

Browse files
committed
Fix pooling performance regression & add IPoolable support
1 parent 0503ba3 commit aaaf9a8

3 files changed

Lines changed: 31 additions & 13 deletions

File tree

src/Pooling/ArrayPool.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33

44
namespace Oxide.Pooling
@@ -120,7 +120,11 @@ public void Return(T[] item)
120120

121121
if (CleanOnReturn)
122122
{
123+
#if NETFRAMEWORK
124+
for (int i = 0; i < item.Length; i++) item[i] = default;
125+
#else
123126
Array.Clear(item, 0, item.Length);
127+
#endif
124128
}
125129

126130
Stack<T[]> store = Pools[item.Length - 1];
@@ -144,7 +148,11 @@ protected override void OnPurge()
144148
while (store.Count > 0)
145149
{
146150
T[] array = store.Pop();
151+
#if NETFRAMEWORK
152+
for (int j = 0; j < array.Length; j++) array[j] = default;
153+
#else
147154
Array.Clear(array, 0, array.Length);
155+
#endif
148156
}
149157
}
150158
}

src/Pooling/IPoolable.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace Oxide.Pooling
2+
{
3+
/// <summary>
4+
/// Implement this interface on pooled types to automatically reset state when returned to a pool.
5+
/// </summary>
6+
public interface IPoolable
7+
{
8+
/// <summary>
9+
/// Resets the object to a clean state for reuse from the pool
10+
/// </summary>
11+
void Reset();
12+
}
13+
}

src/Pooling/PoolFactory.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33

44
namespace Oxide.Pooling
@@ -79,8 +79,6 @@ public void Dispose()
7979

8080
public const int DEFAULT_MAX_POOL_SIZE = 256;
8181

82-
public const bool DEFAULT_ITEM_DISPOSE = false;
83-
8482
#endregion
8583

8684
#region Properties
@@ -93,7 +91,7 @@ public void Dispose()
9391
/// <summary>
9492
/// Returns a new pool with default settings
9593
/// </summary>
96-
public static IPool<T> Default => new PoolFactory<T>(DEFAULT_MAX_POOL_SIZE, DEFAULT_ITEM_DISPOSE);
94+
public static IPool<T> Default => new PoolFactory<T>(DEFAULT_MAX_POOL_SIZE);
9795

9896
/// <summary>
9997
/// Returns a pool instance that doesn't pool items
@@ -104,12 +102,14 @@ public void Dispose()
104102
/// Creates a new pool with custom settings
105103
/// </summary>
106104
/// <param name="maxPoolSize">Max items allowed to pool</param>
107-
/// <param name="itemDispose">Calls dispose on items when they get returned to the pool</param>
108105
/// <returns>The pool provider</returns>
109-
public static IPool<T> Custom(int maxPoolSize = DEFAULT_MAX_POOL_SIZE, bool itemDispose = DEFAULT_ITEM_DISPOSE) => new PoolFactory<T>(maxPoolSize, itemDispose);
106+
public static IPool<T> Custom(int maxPoolSize = DEFAULT_MAX_POOL_SIZE) => new PoolFactory<T>(maxPoolSize);
107+
108+
private static bool IsPoolable { get; }
110109

111110
static PoolFactory()
112111
{
112+
IsPoolable = typeof(IPoolable).IsAssignableFrom(typeof(T));
113113
Shared = Default;
114114
}
115115

@@ -119,12 +119,9 @@ static PoolFactory()
119119

120120
private int MaxPoolSize { get; }
121121

122-
private bool CallItemDispose { get; }
123-
124-
private PoolFactory(int maxPooledSize = 50, bool callItemDispose = false)
122+
private PoolFactory(int maxPooledSize = 50)
125123
{
126124
MaxPoolSize = maxPooledSize <= 0 ? throw new ArgumentOutOfRangeException(nameof(maxPooledSize)) : maxPooledSize;
127-
CallItemDispose = callItemDispose;
128125
Store = new Stack<T>();
129126
}
130127

@@ -143,9 +140,9 @@ public T Take()
143140

144141
public void Return(T item)
145142
{
146-
if (CallItemDispose && item is IDisposable dispose)
143+
if (IsPoolable)
147144
{
148-
dispose.Dispose();
145+
((IPoolable)item).Reset();
149146
}
150147

151148
lock (Store)

0 commit comments

Comments
 (0)