Unity C# 引用池 ReferencePool

news2024/11/26 0:56:54

Unity C# 引用池 ReferencePool

1.目的

对于多次创建的数据使用new 关键字是十分消耗性能的,使用完成后由GC去自动释放,当一个类型的数据频繁创建可以使用引用池进行管理。

2.实现

项目目录
在这里插入图片描述

IReference 接口

要放入引用池的数据只需要继承这个接口即可

namespace ReferencePool
{
    public interface IReference
    {
        void Clear();
    }
}

ReferenceCollection 引用集合

一个类型对应一个引用集合,每次请求从引用集合的队列中获取

namespace ReferencePool
{
    public class ReferenceCollection
    {
        private readonly Queue<IReference> m_References = new Queue<IReference>();
        private Type m_ReferenceType;
        private int m_CurrUsingRefCount;//当前引用的数量
        private int m_AcquireRefCount;//请求引用的总数量
        private int m_ReleaseRefCount;//释放引用的总数量
        private int m_AddRefCount;//添加引用的总数量
        private int m_RemoveRefCount;//移除引用的总数量

        public int CurrUsingRefCount => m_CurrUsingRefCount;
        public int AcquireRefCount => m_AcquireRefCount;
        public int ReleaseRefCount => m_ReleaseRefCount;
        public int AddRefCount => m_AddRefCount;
        public int RemoveRefCount => m_RemoveRefCount;


        public ReferenceCollection(Type refType)
        {
            m_ReferenceType = refType;
            m_CurrUsingRefCount = 0;
            m_AcquireRefCount = 0;
            m_ReleaseRefCount = 0;
            m_AddRefCount = 0;
            m_RemoveRefCount = 0;
        }

        public T Acquire<T>() where T : class, IReference, new()
        {
            if (typeof(T) != m_ReferenceType)
            {
                throw new Exception("类型不相同无法请求!!!");
            }
            m_CurrUsingRefCount++;
            m_AcquireRefCount++;
            lock (m_References)
            {
                if (m_References.Count > 0)
                {
                    return (T)m_References.Dequeue();
                }
            }
            m_AddRefCount++;
            return new T();
        }

        public void Release(IReference reference)
        {
            reference.Clear();
            lock (m_References)
            {
                if (m_References.Contains(reference))
                {
                    throw new Exception("引用已经被释放,请勿重新释放!!!");
                }

                m_References.Enqueue(reference);
            }

            m_CurrUsingRefCount--;
            m_ReleaseRefCount++;
        }

        public void Add<T>(int count) where T : class, IReference, new()
        {
            if (typeof(T) != m_ReferenceType)
            {
                throw new Exception("类型不相同无法添加!!!");
            }
            lock (m_References)
            {
                m_AddRefCount += count;
                while (count-- > 0)
                {
                    m_References.Enqueue(new T());
                }
            }
        }

        public void Remove(int count)
        {
            lock (m_References)
            {
                if(count > m_References.Count)
                {
                    count = m_References.Count;
                }
                m_RemoveRefCount += count;
                while (count-- > 0)
                {
                    m_References.Dequeue();
                }
            }
        }

        public void RemoveAll()
        {
            lock (m_References)
            {
                m_RemoveRefCount += m_References.Count;
                m_References.Clear();
            }
        }
    }
}

ReferencePool 真正的引用池

对引用集合进行统一管理

public static class ReferencePool
    {
        private static readonly Dictionary<Type,ReferenceCollection> m_ReferenceCollections = new Dictionary<Type,ReferenceCollection>();
        public static int Count => m_ReferenceCollections.Count;//获取引用池的数量
        public static void ClearAll()
        {
            lock (m_ReferenceCollections)
            {
                foreach (var reference in m_ReferenceCollections.Values)
                {
                    reference.RemoveAll();
                }
                m_ReferenceCollections.Clear();
            }
        }

        public static T Acquire<T>() where T : class, IReference, new()
        {
            return GetReferenceCollection(typeof(T)).Acquire<T>();
        }

        public static void Release(IReference reference)
        {
            GetReferenceCollection(reference.GetType()).Release(reference);
        }

        public static void Add<T>(int count) where T : class, IReference, new()
        {
            GetReferenceCollection(typeof(T)).Add<T>(count);
        }

        public static void Remove<T>(int count) where T : class, IReference, new()
        {
            GetReferenceCollection(typeof(T)).Remove(count);
        }

        public static void RemoveAll<T>() where T : class, IReference, new()
        {
            GetReferenceCollection(typeof(T)).RemoveAll();
        }

        private static ReferenceCollection GetReferenceCollection(Type type)
        {
            if (type == null)
            {
                throw new Exception("Type 类型 为空!!!");
            }
            ReferenceCollection referenceCollection = null;
            lock (m_ReferenceCollections)
            {
                if(!m_ReferenceCollections.TryGetValue(type,out referenceCollection))
                {
                    referenceCollection = new ReferenceCollection(type);
                    m_ReferenceCollections.Add(type, referenceCollection);
                }
            }
            return referenceCollection;
        }

        public static int GetCurrUsingRefCount<T>() where T : class, IReference, new()
        {
            return GetReferenceCollection(typeof(T)).CurrUsingRefCount;
        }
        public static int GetAcquireRefCount<T>() where T : class, IReference, new()
        {
            return GetReferenceCollection(typeof(T)).AcquireRefCount;
        }
        public static int GetReleaseRefCount<T>() where T : class, IReference, new()
        {
            return GetReferenceCollection(typeof(T)).ReleaseRefCount;
        }
        public static int GetAddRefCount<T>() where T : class, IReference, new()
        {
            return GetReferenceCollection(typeof(T)).AddRefCount;
        }
        public static int GetRemoveRefCount<T>() where T : class, IReference, new()
        {
            return GetReferenceCollection(typeof(T)).RemoveRefCount;
        }
    }

3.测试

namespace ReferencePool
{
    public class Program
    {
        static void Main(string[] args)
        {
            TeacherData teacherData1 = ReferencePool.Acquire<TeacherData>();
            teacherData1.Name = "zzs";
            teacherData1.Age = 20;
            ReferencePool.Release(teacherData1);
            TeacherData teacherData2 = ReferencePool.Acquire<TeacherData>();
            teacherData1.Name = "xxx";
            teacherData1.Age = 18;

            Console.WriteLine(ReferencePool.GetCurrUsingRefCount<TeacherData>());
            Console.WriteLine(ReferencePool.GetAcquireRefCount<TeacherData>());
            Console.WriteLine(ReferencePool.GetReleaseRefCount<TeacherData>());
            Console.WriteLine(ReferencePool.GetAddRefCount<TeacherData>());
            Console.WriteLine(ReferencePool.GetRemoveRefCount<TeacherData>());
            Console.ReadKey();
        }
    }

    public class TeacherData : IReference
    {
        public string Name;
        public int Age;
        public void Clear()
        {
            Name = string.Empty;
            Age = 0;
        }
    }
}

4.总结

重复使用的对象只创建有限次,避免来回实例化对象的开销

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/903884.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023.08.20 学习周报

文章目录 摘要文献阅读1.题目2.现有问题3.解决方案4.本文贡献5.方法5.1 利用长短期记忆网络学习时空演化特征5.2 构建用于气象辅助信息编码的堆叠自编码器5.3 使用多任务学习发现全市通用模式5.4 模型 6. 实验6.1 数据集6.2 实验设置6.3 实验结果 7.结论8.展望 大气污染物传输总…

04 - Vue3语法系统进阶 - 全面掌握Vue3特性

目录 01-ref属性在元素和组件上的分别使用02-利用nextTick监听DOM更新后的情况03-自定义指令与自定义全局属性及应用场景04-复用组件功能之Mixin混入05-插件的概念及插件的实现06-transition动画与过渡的实现07-动态组件与keep-alive组件缓存08-异步组件与Suspense一起使用09-跨…

在线SHA256计算哈希(不可逆的加密又称摘要)工具

具体请前往&#xff1a; 在线计算Sha256摘要工具

7.10 SpringBoot实战 全局异常处理

文章目录 前言RestControllerAdvice项目实战最后 前言 在一个项目中&#xff0c;异常处理 是你无法绕过去的话题&#xff01; 不论你多牛逼&#xff0c;你写的代码都可能会出现异常&#xff0c;有的异常非常容易测试出来&#xff0c;但有的异常却需要在非常极端情况下才会出现…

线性代数的学习和整理7:各种特殊矩阵(草稿-----未完成)

目录 1 单位矩阵 为什么单位矩阵I是 [1,0;0,1]T 而不是[1,1;1,1]T 2 旋转矩阵 3 伸缩矩阵 放大缩小倍数矩阵 4 镜像矩阵 5 剪切矩阵 矩阵 行向量 列向量 方阵 1 单位矩阵 [ 1 0 0 1] 为什么单位矩阵I是 [1,0;0,1]T 而不是[1,1;1,1]T 因为 矩阵 [1,0;0,1] 代表…

netty(一):NIO——处理消息边界

处理消息边界 为什么要处理边界 因为会存在半包和粘包的问题 1.客户端和服务端约定一个固定长度 优点&#xff1a;简单 缺点&#xff1a;可能造成浪费 2.客户端与服务端约定一个固定分割符 *缺点 效率低 3.先发送长度&#xff0c;再发送数据 TLV格式&#xff1a; type…

LeetCode 1162. As Far from Land as Possible【多源BFS】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

网络编程(字节序)

一、字节序的概念 字节序是指不同类型CPU主机&#xff0c;内存存储 多字节整数 序列的方式。 float, char, 字符串均没有字节序的说法 short, int , long , long long 有字节序的说法 小端字节序&#xff1a;低字节存储在低地址&#xff0c;高字节存储在高地址 大端字节序…

基于IMX6ULLmini的linux裸机开发系列九:时钟控制模块

时钟控制模块 核心 4个层次配置芯片时钟 晶振时钟 PLL与PFD时钟 PLL选择时钟 根时钟/外设时钟 系统时钟来源 RTC时钟源&#xff1a;32.768KHz 系统时钟&#xff1a;24MHz&#xff0c;作为芯片的主晶振使用 PLL和PFD倍频时钟 7路锁相环电路&#xff08;每个锁相环电路…

Maven打包后的jar文件只有几kb情况解决方法

1、pom文件添加如下代码 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build> 2、打开ide的maven工具侧边栏…

solidwords(5)

我们打算从上面画出总体&#xff0c;再从上面、侧面切除 最后成品

Java网络编程(二)NIO实现简易的多人聊天

服务端实现 package com.bierce.io; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Set; //服务器端 public cl…

红绿灯识别、倒计时识别(毕业设计)

交通标志识别 本项目使用YOLO 模型&#xff0c;并在对数字信号灯进行数字识别时采用opencv算法。 环境安装 所需环境 python 3.7.11 torch1.2.00 使用 pip install -r requirements.txt安装所需的包。 文件下载 训练所需的预训练权重可在百度网盘中下载。 链接&#xf…

ARM体系结构学习笔记:任何算法可通过下面的三种模式组合而成

任何算法可通过下面的三种模式组合而成 条件跳转和无条件跳转 条件命名规则 关于比较的一些哲学问题 汇编实现if else [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R8R5cYTQ-1692236026691)(https://cdn.jsdelivr.net/gh/nzcv/picgo/202201172242…

Gin+微服务实现抖音视频上传到七牛云

文章目录 安装获取凭证Gin处理微服务处理 如果你对Gin和微服务有一定了解&#xff0c;看本文较容易。 安装 执行命令&#xff1a; go get github.com/qiniu/go-sdk/v7获取凭证 Go SDK 的所有的功能&#xff0c;都需要合法的授权。授权凭证的签算需要七牛账号下的一对有效的A…

回归预测 | MATLAB实现BES-LSSVM秃鹰搜索算法优化最小二乘支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现BES-LSSVM秃鹰搜索算法优化最小二乘支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现BES-LSSVM秃鹰搜索算法优化最小二乘支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&a…

手写模拟SpringBoot核心流程(二):实现Tomcat和Jetty的切换

实现Tomcat和Jetty的切换 前言 上一篇文章我们聊到&#xff0c;SpringBoot中内置了web服务器&#xff0c;包括Tomcat、Jetty&#xff0c;并且实现了SpringBoot启动Tomcat的流程。 那么SpringBoot怎样自动切换成Jetty服务器呢&#xff1f; 接下来我们继续学习如何实现Tomcat…

网络编程面试笔试题

一、OSI 7层模型&#xff0c;TCP/IP 4层模型 5层模型。 以及每一层的功能&#xff08;重点&#xff1a;第三层 第四层&#xff09; 答&#xff1a; 7层模型&#xff08;①物理层&#xff1a;二进制比特流传输&#xff0c;②数据链路层&#xff1a;相邻结点的可靠传输&#xf…

Ctfshow web入门 命令执行RCE篇 web29-web77 与 web118-web124 详细题解 持续更新中

Ctfshow 命令执行 web29 pregmatch是正则匹配函数&#xff0c;匹配是否包含flag&#xff0c;if(!preg_match("/flag/i", $c))&#xff0c;/i忽略大小写 可以利用system来间接执行系统命令 flag采用f*绕过&#xff0c;或者mv fl?g.php 1.txt修改文件名&#xff0c…

Docker搭建LNMP----(超详细)

目录 ​编辑 一、项目环境 1.1 所有安装包下载&#xff1a; 1.3 服务器环境 1.4任务需求 二、Ngin 2.1、建立工作目录 2.2 编写 Dockerfile 脚本 2.3准备 nginx.conf 配置文件 2.4生成镜像 2.5创建自定义网络 2.6启动镜像容器 2.7验证 nginx、 三、Mysql 3.1建立…