C# ObjectPool测试

发布于:2024-06-30 ⋅ 阅读:(129) ⋅ 点赞:(0)
using Microsoft.Extensions.ObjectPool;       

        private ArrayPool<int> _arrayPool = System.Buffers.ArrayPool<int>.Create(1024*1024*1024, 5);

        private DefaultPooledObjectPolicy<A> _poolPolicy = new DefaultPooledObjectPolicy<A>();
        private ObjectPool<A> _pool;



        private void button1_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    RunObjByPool();
                    Thread.Sleep(1000);
                }
            });
        }

        private void RunObjByPool()
        {
            ShowLog("RunByPool-Started");
            var list = new List<A>();
            var rand = new Random();
            var bytes = new int[100];
            for (var i = 0; i < 100; i++)
            {
                var item1 = _pool.Get();
                item1.ID = i;
                var chars = $"hello{i + 1}".ToArray();
                item1.StrLen = chars.Length;
                Array.Clear(item1.F1, 0, item1.F1.Length);
                Array.Copy(chars, item1.F1, chars.Length);
                Array.Clear(item1.F2, 0, item1.F2.Length);
                for (var j = 0; j < 100; j++)
                    bytes[j] = i;
                Array.Copy(bytes, item1.F2, bytes.Length);
                item1.Weight = rand.Next(100);
                Debug.WriteLine(item1.ToString());
                list.Add(item1);
            }
            foreach(var item in list)
                _pool.Return(item);
            ShowLog("RunByPool-Finished");
        }

        private void RunNewObj()
        {
            ShowLog("Run-Started");
            var rand = new Random();
            var list = new List<A>();
            var bytes = new int[100];
            for (var i = 0; i < 100; i++)
            {
                var item1 = new A();
                item1.ID = i;
                var chars = $"hello{i + 1}".ToArray();
                item1.StrLen = chars.Length;
                Array.Clear(item1.F1, 0, item1.F1.Length);
                Array.Copy(chars, item1.F1, chars.Length);
                Array.Clear(item1.F2, 0, item1.F2.Length);
                for (var j = 0; j < 100; j++)
                    bytes[j] = i;
                Array.Copy(bytes, item1.F2, bytes.Length);
                item1.Weight = rand.Next(100);
                Debug.WriteLine(item1.ToString());
                list.Add(item1);
            }
            ShowLog(list.Count.ToString());
            ShowLog("Run-Finished");
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _pool = new DefaultObjectPool<A>(_poolPolicy, 1000);
        }
        private void ShowLog(string log)
        {
            Invoke(new Action(()=>textBox1.AppendText($"{log}\r\n")));
        }
        private void button2_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    RunNewObj();
                    Thread.Sleep(1000);
                }
            });
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() => {
                while (true)
                {
                    RunArrByPool();
                    Thread.Sleep(1000);
                }
            });
        }

        private void RunArrByPool()
        {
            double res = 0;
            for(var i = 1;  i < 1000; i++)
            {
                var arr = _arrayPool.Rent(i * 100);
                for (var j = 0; j < arr.Length; j++)
                    arr[j] = i * j;
                res += arr.Average();
                _arrayPool.Return(arr);
            }
            ShowLog($"{res}");
        }

        private void RunArr()
        {
            double res = 0;
            for (var i = 1; i < 1000; i++)
            {
                var arr = new int[i * 100];
                for (var j = 0; j < arr.Length; j++)
                    arr[j] = i * j;
                res += arr.Average();
            }
            ShowLog($"{res}");
        }

        private void button4_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() => {
                while (true)
                {
                    RunArr();
                    Thread.Sleep(1000);
                }
            });
        }

        private void button5_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() => {
                while (true)
                {
                    RunArrByPool();
                    Thread.Sleep(1000);
                }
            });
        }
    

    public class A
    {
        public int ID { get; set; }
        public int StrLen { get; set; }
        public char[] F1 { get; set; } = new char[1024*1024];
        public int[] F2 { get; set; } = new int[1024 * 1024];
        public int Age { get; set; }
        public float Weight { get; set; }

        public override string ToString()
        {
            return $"{ID}-{new string(F1, 0, StrLen)}-{F2.Average()}-{Age}-{Weight}\r\n";
        }
    }

ObjectPool测试结论:DefaultObjectPool的第二个参数设置合理的缓存大小,应用过程中可以确保无GC,内存稳定;如不启用缓存机制,大量new A对象,频繁GC,内存量跳跃。

ArrayPool测试结论:引入ArrayPool后,从其中获取内存,进程无GC,无WorkSet变化;改为数组方式大量GC,内存暴涨。

查看Get、Return方法,里面有无锁安全机制,并使用线程安全容器队列存储,因此多线程下放心使用。


网站公告

今日签到

点亮在社区的每一天
去签到