diff --git a/Source/Engine/Engine/NativeInterop.Managed.cs b/Source/Engine/Engine/NativeInterop.Managed.cs index d3c644072..41ace593b 100644 --- a/Source/Engine/Engine/NativeInterop.Managed.cs +++ b/Source/Engine/Engine/NativeInterop.Managed.cs @@ -382,7 +382,8 @@ namespace FlaxEngine.Interop private static class ManagedHandlePool { - private const int WeakPoolCollectionThreshold = 10000000; + private const int WeakPoolCollectionSizeThreshold = 10000000; + private const int WeakPoolCollectionTimeThreshold = 500; private static ulong normalHandleAccumulator = 0; private static ulong pinnedHandleAccumulator = 0; @@ -397,6 +398,7 @@ namespace FlaxEngine.Interop [ThreadStatic] private static Dictionary weakPoolOther; [ThreadStatic] private static ulong nextWeakPoolCollection; [ThreadStatic] private static int nextWeakPoolGCCollection; + [ThreadStatic] private static long lastWeakPoolCollectionTime; /// /// Tries to free all references to old weak handles so GC can collect them. @@ -411,19 +413,22 @@ namespace FlaxEngine.Interop { weakPool = new Dictionary(); weakPoolOther = new Dictionary(); - nextWeakPoolGCCollection = GC.CollectionCount(0); + nextWeakPoolGCCollection = GC.CollectionCount(0) + 1; return; } - // Collect right after garbage collection or whenever the pool gets too large + // Try to swap pools after garbage collection or whenever the pool gets too large var gc0CollectionCount = GC.CollectionCount(0); - if (gc0CollectionCount < nextWeakPoolGCCollection && weakPool.Count < WeakPoolCollectionThreshold) + if (gc0CollectionCount < nextWeakPoolGCCollection && weakPool.Count < WeakPoolCollectionSizeThreshold) return; - nextWeakPoolGCCollection = gc0CollectionCount + 1; - var swap = weakPoolOther; - weakPoolOther = weakPool; - weakPool = swap; + // Prevent huge allocations from swapping the pools in the middle of the operation + if (System.Diagnostics.Stopwatch.GetElapsedTime(lastWeakPoolCollectionTime).TotalMilliseconds < WeakPoolCollectionTimeThreshold) + return; + lastWeakPoolCollectionTime = System.Diagnostics.Stopwatch.GetTimestamp(); + + // Swap the pools and release the oldest pool for GC + (weakPool, weakPoolOther) = (weakPoolOther, weakPool); weakPool.Clear(); }