Przeglądaj źródła

Early out in ObjectPool to avoid loop execution (#1985)

tomatosalat0 9 miesięcy temu
rodzic
commit
6cb6d5dd8d
1 zmienionych plików z 9 dodań i 1 usunięć
  1. 9 1
      Jint/Pooling/ObjectPool.cs

+ 9 - 1
Jint/Pooling/ObjectPool.cs

@@ -57,6 +57,7 @@ internal sealed class ObjectPool<T> where T : class
     // expect to be able to satisfy most requests from it.
     // expect to be able to satisfy most requests from it.
     private T _firstItem;
     private T _firstItem;
     private readonly Element[] _items;
     private readonly Element[] _items;
+    private int _currentSlowPooledItems;
 
 
     // factory is stored for the lifetime of the pool. We will call this only when pool needs to
     // factory is stored for the lifetime of the pool. We will call this only when pool needs to
     // expand. compared to "new T()", Func gives more flexibility to implementers and faster
     // expand. compared to "new T()", Func gives more flexibility to implementers and faster
@@ -158,13 +159,16 @@ internal sealed class ObjectPool<T> where T : class
 
 
     private T AllocateSlow()
     private T AllocateSlow()
     {
     {
-        var items = _items;
+        if (_currentSlowPooledItems <= 0)
+            return CreateInstance();
 
 
+        var items = _items;
         for (int i = 0; i < items.Length; i++)
         for (int i = 0; i < items.Length; i++)
         {
         {
             T inst = items[i].Value;
             T inst = items[i].Value;
             if (inst is not null)
             if (inst is not null)
             {
             {
+                _currentSlowPooledItems--;
                 items[i].Value = null;
                 items[i].Value = null;
                 return inst;
                 return inst;
             }
             }
@@ -202,6 +206,9 @@ internal sealed class ObjectPool<T> where T : class
     private void FreeSlow(T obj)
     private void FreeSlow(T obj)
     {
     {
         var items = _items;
         var items = _items;
+        if (_currentSlowPooledItems >= items.Length)
+            return;
+
         for (int i = 0; i < items.Length; i++)
         for (int i = 0; i < items.Length; i++)
         {
         {
             if (ReferenceEquals(items[i].Value, null))
             if (ReferenceEquals(items[i].Value, null))
@@ -209,6 +216,7 @@ internal sealed class ObjectPool<T> where T : class
                 // Intentionally not using interlocked here.
                 // Intentionally not using interlocked here.
                 // In a worst case scenario two objects may be stored into same slot.
                 // In a worst case scenario two objects may be stored into same slot.
                 // It is very unlikely to happen and will only mean that one of the objects will get collected.
                 // It is very unlikely to happen and will only mean that one of the objects will get collected.
+                _currentSlowPooledItems++;
                 items[i].Value = obj;
                 items[i].Value = obj;
                 break;
                 break;
             }
             }