更多代码细节,球球各位观众老爷给鄙人的开源项目点个Star,持续更新中~ 项目开源地址
需要实现对象池的对象都要继承IPool接口
namespace Common.Summer.core;
public interface IPool
{
void ReturnPool(); //放回对象池,释放持有的引用
}
using System.Collections.Concurrent;
using Serilog;
namespace Common.Summer;
///
/// 泛型对象池管理器
/// 服务端对象池,线程安全
///
public class ObjPoolLockManager : BaseManager<ObjPoolLockManager>
{
private readonly ConcurrentDictionary<string, PoolNode> pool = new();
private static readonly object _poolLock = new();
public int test;
///
/// 缓存池节点
///
private class PoolNode
{
public readonly List<object> poolList;
private static readonly object lockObj = new(); // 用于保护LinkedList的访问
public PoolNode()
{
poolList = new List<object>();
}
public void Push(object obj)
{
lock (lockObj) poolList.Add(obj);
}
public object PopTop()
{
object obj = null;
lock (lockObj)
{
if (poolList.Count <= 0) return obj;
obj = poolList[^1];
poolList.RemoveAt(poolList.Count - 1);
}
return obj;
}
public int Count => poolList.Count;
}
///
/// 从对象池获取对象
///
public async ValueTask<T> PopAsync<T>(Func<Task<T>> objectFactory = null, Action<T> callback = null)
where T : class
{
T? obj;
if (pool.TryGetValue(typeof(T).FullName, out var poolNode) && poolNode.Count > 0)
obj = poolNode.PopTop() as T;
else
obj = await objectFactory();
lock (_poolLock)
{
callback?.Invoke(obj);
return obj;
}
}
public T? Pop<T>(Func<T> objectFactory, Action<T> callback = null)
{
lock (_poolLock)
{
T? obj;
if (pool.TryGetValue(typeof(T).FullName, out var poolNode) && poolNode.Count > 0)
{
Interlocked.Add(ref test, 1);
obj = (T)poolNode.PopTop();
}
else
obj = objectFactory();
callback?.Invoke(obj);
return obj;
}
}
///
/// 将对象归还到池中
///
public void Push<T>(T obj)
{
var poolNode = pool.GetOrAdd(typeof(T).FullName, _ => new PoolNode());
poolNode.Push(obj);
}
///
/// 预加载对象池
///
public async ValueTask PreloadAsync<T>(int count, Func<Task<T>> objectFactory)
{
var poolNode = pool.GetOrAdd(typeof(T).FullName, _ => new PoolNode());
// 异步预加载指定数量的对象
for (var i = 0; i < count; i++)
{
var obj = await objectFactory();
poolNode.Push(obj);
}
}
///
/// 清空对象池
///
public void Clear()
{
foreach (var type in pool.Keys)
RemoveType(type);
pool.Clear();
}
///
/// 移除指定类型的对象池
///
public void RemoveType(string type)
{
if (!pool.TryGetValue(type, out var poolNode)) return;
poolNode.poolList.Clear();
pool.TryRemove(type, out _);
}
}
namespace Common.Summer.core;
public static class MoonExtension
{
public static T MoonObjGetPool<T>(this object obj, Func<T> _fun, Action<T> callback = null) where T : class
{
return ObjPoolLockManager.Instance.Pop( _fun, callback);
}
public static void MoonObjPushPool<T>(this T obj) //提供便利的对象池放入语法
{
ObjPoolLockManager.Instance.Push(obj);
//如:this.MoonObjPushPool();
}
}
=== 压测报告 ===
运行时间: 30.05s
计划任务总数: 7377
实际执行次数: 69689
QPS: 2319/s(只测试了单一线程的Task处理)
- 对象池使用次数: 7324
using System.Diagnostics;
using Common.Summer;
using Org.BouncyCastle.Utilities.Zlib;
using Serilog;
namespace TestClient;
public class SchedulerStressTest
{
private const int ThreadCount = 4; // 并发线程数
private const int TasksPerSecond = 1000; // 每秒任务数
private const int TestDurationSec = 30; // 测试持续时间
public static async Task RunTest()
{
//初始化日志环境
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug() // debug, info, warn, error 优先级
.WriteTo.Async(loggerSink =>loggerSink.Console()) //输出到控制台
.WriteTo.Async(loggerSink => loggerSink.File("logs\\test.txt", rollingInterval: RollingInterval.Day)) //输出到文件,多久生成
.CreateLogger();
var scheduler = new Scheduler();
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(TestDurationSec));
// 测试指标
var totalExecuted = 0L;
var totalScheduled = 0L;
var stopwatch = Stopwatch.StartNew();
scheduler.Start();
// 创建压测任务(持续生成)
var producers = Enumerable.Range(0, ThreadCount).Select(_ =>
Task.Run(async () =>
{
var rnd = new Random();
while (!cts.IsCancellationRequested)
{
var taskId = scheduler.AddTask(() =>
{
Thread.SpinWait(1000); // 1ms负载
Interlocked.Increment(ref totalExecuted);
},
TimeSpan.FromMilliseconds(10),
repeatCount: 10);
Interlocked.Increment(ref totalScheduled);
Log.Debug("{0} {1}", totalExecuted, totalScheduled);
// 10%概率取消
if (rnd.Next(0, 10) == 0)
{
scheduler.CancelTask(taskId);
}
// 控制任务生成速率
if (totalScheduled >= TasksPerSecond * TestDurationSec) break;
try
{
await Task.Delay(1000 / (TasksPerSecond / ThreadCount), cts.Token);
}
catch (Exception e)
{
break;
}
}
}, cts.Token)
).ToArray();
// 等待测试时间结束
await Task.WhenAll(producers);
scheduler.Stop(); // 确保调度器停止
// 输出测试报告
stopwatch.Stop();
Console.WriteLine($"=== 压测报告 ===");
Console.WriteLine($"运行时间: {stopwatch.Elapsed.TotalSeconds:F2}s");
Console.WriteLine($"计划任务总数: {totalScheduled}");
Console.WriteLine($"实际执行次数: {totalExecuted}");
Console.WriteLine($"QPS: {totalExecuted / stopwatch.Elapsed.TotalSeconds:F0}/s");
//Console.WriteLine($" - 对象池使用次数: {ObjPoolLockManager.Instance.test}");
}
}
//
public static class Program
{
public static async Task Main()
{
await SchedulerStressTest.RunTest();
Console.ReadKey(); // 防止控制台立即关闭
}
}