mirror of https://github.com/SixLabors/ImageSharp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
3.9 KiB
101 lines
3.9 KiB
// Copyright (c) Six Labors.
|
|
// Licensed under the Apache License, Version 2.0.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using Microsoft.DotNet.RemoteExecutor;
|
|
using SixLabors.ImageSharp.Memory.Internals;
|
|
using Xunit;
|
|
|
|
namespace SixLabors.ImageSharp.Tests.Memory.Allocators
|
|
{
|
|
public partial class UniformUnmanagedMemoryPoolTests
|
|
{
|
|
[CollectionDefinition(nameof(NonParallelTests), DisableParallelization = true)]
|
|
public class NonParallelTests
|
|
{
|
|
}
|
|
|
|
[Collection(nameof(NonParallelTests))]
|
|
public class Trim
|
|
{
|
|
[Fact]
|
|
public void TrimPeriodElapsed_TrimsHalfOfUnusedArrays()
|
|
{
|
|
RemoteExecutor.Invoke(RunTest).Dispose();
|
|
static void RunTest()
|
|
{
|
|
var trimSettings = new UniformUnmanagedMemoryPool.TrimSettings { TrimPeriodMilliseconds = 5_000 };
|
|
var pool = new UniformUnmanagedMemoryPool(128, 256, trimSettings);
|
|
|
|
UnmanagedMemoryHandle[] a = pool.Rent(64);
|
|
UnmanagedMemoryHandle[] b = pool.Rent(64);
|
|
pool.Return(a);
|
|
Assert.Equal(128, UnmanagedMemoryHandle.TotalOutstandingHandles);
|
|
Thread.Sleep(15_000);
|
|
|
|
// We expect at least 2 Trim actions, first trim 32, then 16 arrays.
|
|
// 128 - 32 - 16 = 80
|
|
Assert.True(
|
|
UnmanagedMemoryHandle.TotalOutstandingHandles <= 80,
|
|
$"UnmanagedMemoryHandle.TotalOutstandingHandles={UnmanagedMemoryHandle.TotalOutstandingHandles} > 80");
|
|
pool.Return(b);
|
|
}
|
|
}
|
|
|
|
#if NETCORE31COMPATIBLE
|
|
public static readonly bool Is32BitProcess = !Environment.Is64BitProcess;
|
|
private static readonly List<byte[]> PressureArrays = new List<byte[]>();
|
|
|
|
[ConditionalFact(nameof(Is32BitProcess))]
|
|
public static void GC_Collect_OnHighLoad_TrimsEntirePool()
|
|
{
|
|
RemoteExecutor.Invoke(RunTest).Dispose();
|
|
static void RunTest()
|
|
{
|
|
Assert.False(Environment.Is64BitProcess);
|
|
const int OneMb = 1024 * 1024;
|
|
|
|
var trimSettings = new UniformUnmanagedMemoryPool.TrimSettings { HighPressureThresholdRate = 0.2f };
|
|
|
|
GCMemoryInfo memInfo = GC.GetGCMemoryInfo();
|
|
int highLoadThreshold = (int)(memInfo.HighMemoryLoadThresholdBytes / OneMb);
|
|
highLoadThreshold = (int)(trimSettings.HighPressureThresholdRate * highLoadThreshold);
|
|
|
|
var pool = new UniformUnmanagedMemoryPool(OneMb, 16, trimSettings);
|
|
pool.Return(pool.Rent(16));
|
|
Assert.Equal(16, UnmanagedMemoryHandle.TotalOutstandingHandles);
|
|
|
|
for (int i = 0; i < highLoadThreshold; i++)
|
|
{
|
|
byte[] array = new byte[OneMb];
|
|
TouchPage(array);
|
|
PressureArrays.Add(array);
|
|
}
|
|
|
|
GC.Collect();
|
|
GC.WaitForPendingFinalizers();
|
|
GC.Collect();
|
|
GC.WaitForPendingFinalizers(); // The pool should be fully trimmed after this point
|
|
|
|
Assert.Equal(0, UnmanagedMemoryHandle.TotalOutstandingHandles);
|
|
|
|
static void TouchPage(byte[] b)
|
|
{
|
|
uint size = (uint)b.Length;
|
|
const uint pageSize = 4096;
|
|
uint numPages = size / pageSize;
|
|
|
|
for (uint i = 0; i < numPages; i++)
|
|
{
|
|
b[i * pageSize] = (byte)(i % 256);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|