热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Unity/C#:优化字符串操作产生的GC【UsingZString】

前言:最近被要求改关于字符串操作中的GC,比如:数字转文本、字符串拼接等。一般来讲有的可以避免,但有的很难避免。比如NumberToString的操作,总归是写在逻辑的硬需求里面的
前言:

最近被要求改关于字符串操作中的GC,比如:数字转文本、字符串拼接等。一般来讲有的可以避免,但有的很难避免。比如Number To String的操作,总归是写在逻辑的硬需求里面的(等级、时间、飘血等)。

《Unity/ C#:优化字符串操作产生的GC【Using ZString】》

如上图所示,这个是Int32.ToString的时候产生的GC,其他的数值转文本也差不多一个情况。即便调用其他的API,最终都会走到这边一步,一个String.InternalAllocateStr就会产生约42B的GC出来。当然这个是可以考虑作为优化的点,但是这个方法属于C#底层了,我们需要对String进行扩充来避免他的GC情况出现。

这个时候,通过朋友的介绍,发现了一个叫ZString的东西,他的出现就是为了避免这种GC的问题,于是就开心地拿来测试了一下。

 

ZString:

关于ZString的介绍和源代码见下面的链接, 这里就不赘述了。

介绍:https://coh5.cn/p/1ace6338.html

GitHub:https://github.com/871041532/zstring

 

1、使用:

这个ZString的使用方法较为麻烦,自然不能像C#的String那么自如。例如一个将Int转为字符串的操作,需要这么写:

using (ZString.Block())
{
int number = 16578187;
ZString zStr = number;
string str2 = zStr.ToString();
}

对的,他在操作的时候要先把这个东西进行Block操作,而出了这个作用域它的值有可能会被改变。

注意:不可使用ZString作为类的成员变量,不建议在Using作用域中写超大For循环。

首次调用时会初始化类,分配各种空间,建议游戏启动时调用一次using(ZString.block()){}

//使用方式:
// 1.当update每帧刷新标签显示,或者该字符串是短时间使用的则使用如下方式:
using (ZString.Block())
{
ZString a="hello world";
a.text=a
}
// 此方式设置的string值位于深拷贝缓存中,一定时间可能会改变。
//2.比如路径,或者面板上常驻的字符串。需要常驻的则需要intern一下在作用域外使用
using (ZString.Block())
{
ZString a="Assets/";
ZString b=a+"prefabs/"+"/solider.prefab";
a.path=b.Intern();
}
//此方式设置的string值位于intern表中,游戏运行期间不会改变。

 

警告:Unity UGUI的Text组件不能直接使用上述方法赋值!!!

无论是使用 aText.text=aZString.toString(),还是aText.text=aZString都会造成设置值和显示值不一致。虽然在本帧打印出来的值都是正确的,但是实际显示的值是不对的(实际上只有字符串长度是正确的),如下代码:

《Unity/ C#:优化字符串操作产生的GC【Using ZString】》

其跑出来的结果如下:

《Unity/ C#:优化字符串操作产生的GC【Using ZString】》

可见在本帧怎么 样看都是对的,但实际上Text上显示的文本确实是个诡异的错值。

修正方法:用ZString.Intern()取代ZString.ToString();

 

警告2:即便用上述方法进行修正,虽然解决了显示文本不对的问题,但是却因为Intern方法产生了GC!因为其底层调用了New String方法:

《Unity/ C#:优化字符串操作产生的GC【Using ZString】》

如图,当你的数字是从来没有出现过的时候,就会产生一个新的字符串,此时就会导致32B的GC。而这个原因归根结底就是因为Text.text被修改后,Unity并没有立即修改文本显示(感觉上是这样)。虽然看了源码也没发现有什么地方不对,但实际上就是这种效果。

后来苦思冥想想不通,用了个很弱智的方法来解决:

在每一次对Text进行赋值后,同时更改Text的颜色。其颜色用2个颜色交替,一个是原来的颜色,另一个是比原来的颜色其透明度略低0.005的颜色(表现上基本看不出差别);或者修改文本框的长宽。

至于为什么,只能说能力有限了……

 

2、效率测试:

string和ZString的NumberToString对比:

《Unity/ C#:优化字符串操作产生的GC【Using ZString】》

string :总计1ms,8.6KB GC;

ZString:总计约1.14+0.98+0.48=2.6ms,0GC;

 

字符串拼接测试:

《Unity/ C#:优化字符串操作产生的GC【Using ZString】》

String:    总计0.48ms,8.6 kb GC;

ZString:  总计2.4ms,0 GC;

 

结论:

这个ZString算是所有的字符串补充方案里面优化得最好的了,但是比起string来单说速度而言有不小的差距。在进行NumberToString操作的时候,其速度是原生String的1/3;而在进行字符串拼接的时候,速度降到1/6 。string即便是在有40B的GC的情况下,其总体速度还是要快上不少。

但好在没有GC,所以还是各位看自己的项目情况使用吧。

 

警告:如果直接使用GitHub下载下载的那个ZString来使用,虽然电脑上没什么毛病,但是打包成安卓如果用了IL2CPP就会报错导致打包失败!

Failed running C:\Program Files\Unity\Editor\Data\il2cpp/build/il2cpp.exe 

use of undeclared identifier

《Unity/ C#:优化字符串操作产生的GC【Using ZString】》

《Unity/ C#:优化字符串操作产生的GC【Using ZString】》

从报错情况下来看是因为一些结构体没有定义导致的,而源码的结构体都是写在类外面的。所以要做的就是把这些结构体移动到类里面(反正也没别的地方要用):

《Unity/ C#:优化字符串操作产生的GC【Using ZString】》

这样就可以了,亲测 可用~

还看到一个帖子:https://blog.csdn.net/qqqqqq8633542/article/details/80654218?utm_source=blogxgwz3;说是把ZString放在Plugins目录下也可以。不过他说的是XCode编译不过,我想应该是差不多一样的问题。

 

 

 

 

最后,感谢下海的某位骚骚的大佬~~~~


推荐阅读
  • 在Mac系统中安装Hexo时,如果遇到“Error: Cannot find module './build/Release/DTraceProviderBindings’”错误,可以通过以下步骤解决:首先确保已正确安装Node.js和npm,然后尝试运行`npm install hexo --no-optional`。若问题依然存在,建议检查环境变量配置,并参考Hexo官方文档进行进一步排查。 ... [详细]
  • 在ElasticStack日志监控系统中,Logstash编码插件自5.0版本起进行了重大改进。插件被独立拆分为gem包,每个插件可以单独进行更新和维护,无需依赖Logstash的整体升级。这不仅提高了系统的灵活性和可维护性,还简化了插件的管理和部署过程。本文将详细介绍这些编码插件的功能、配置方法,并通过实际生产环境中的应用案例,展示其在日志处理和监控中的高效性和可靠性。 ... [详细]
  • 本文汇集了我在网络上搜集以及在实际面试中遇到的前端开发面试题目,并附有详细解答。无论是初学者还是有一定经验的开发者,都应深入理解这些问题背后的原理,通过系统学习和透彻研究,逐步形成自己的知识体系和技术框架。 ... [详细]
  • POJ 2482 星空中的星星:利用线段树与扫描线算法解决
    在《POJ 2482 星空中的星星》问题中,通过运用线段树和扫描线算法,可以高效地解决星星在窗口内的计数问题。该方法不仅能够快速处理大规模数据,还能确保时间复杂度的最优性,适用于各种复杂的星空模拟场景。 ... [详细]
  • 在安装 iOS 开发所需的 CocoaPods 时,用户可能会遇到多种问题。其中一个常见问题是,在执行 `pod setup` 命令后,系统无法连接到 GitHub 以更新 CocoaPods/Specs 仓库。这可能是由于网络连接不稳定、GitHub 服务器暂时不可用或本地配置错误等原因导致。为解决此问题,建议检查网络连接、确保 GitHub API 限制未被触发,并验证本地配置文件是否正确。 ... [详细]
  • 为了优化用户体验,本文探讨了如何调整下拉菜单的宽度。通过合理设置宽度,可以提升界面的美观性和易用性。文章提供了具体的代码示例,帮助开发者实现这一目标。例如,可以通过 CSS 或 JavaScript 来动态调整下拉菜单的宽度,确保其在不同设备和屏幕尺寸上都能保持良好的显示效果。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 提升视觉效果:Unity3D中的HDR与Bloom技术(高动态范围成像与光线散射)
    提升视觉效果:Unity3D中的HDR与Bloom技术(高动态范围成像与光线散射) ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 在 CentOS 7 系统中安装 Scrapy 时遇到了一些挑战。尽管 Scrapy 在 Ubuntu 上安装简便,但在 CentOS 7 上需要额外的配置和步骤。本文总结了常见问题及其解决方案,帮助用户顺利安装并使用 Scrapy 进行网络爬虫开发。 ... [详细]
  • 当程序首次启动时,由于代码尚未加载到内存中,会触发大量的页面错误,从而需要从磁盘读取代码。那么,当程序终止后,这些二进制文件是否会继续驻留在内存中呢?本文将探讨程序退出后的内存状态及其对系统性能的影响。 ... [详细]
  • 体积小巧的vsftpd与pureftpd Docker镜像在Unraid系统中的详细配置指南:支持TLS加密及IPv6协议
    本文详细介绍了如何在Unraid系统中配置体积小巧的vsftpd和Pure-FTPd Docker镜像,以支持TLS加密和IPv6协议。通过这些配置,用户可以实现安全、高效的文件传输服务,适用于各种网络环境。配置过程包括镜像的选择、环境变量的设置以及必要的安全措施,确保了系统的稳定性和数据的安全性。 ... [详细]
  • 如何在您的计算机上配置Python和PyCharm开发环境
    本文详细介绍了在Windows 10系统上配置Python和PyCharm开发环境的步骤。内容包括Python的安装与卸载、PyCharm的安装与卸载,以及如何在Windows 10中通过双击安装文件“python-3.7.2-amd64.exe”来完成Python的安装。此外,还提供了关于环境变量配置和基本设置的实用建议,帮助用户快速搭建高效的开发环境。 ... [详细]
  • 如何在任意浏览器中轻松安装并使用VSCode——Codeserver简易指南
    code-server 是一款强大的工具,允许用户在任何服务器上部署 VSCode,并通过浏览器进行访问和使用。这一解决方案不仅简化了开发环境的搭建过程,还提供了高度灵活的工作方式。用户只需访问 GitHub 上的官方仓库(GitHub-coder/code-server),即可获取详细的安装和配置指南,快速启动并运行 code-server。无论是个人开发者还是团队协作,code-server 都能提供高效、便捷的代码编辑体验。 ... [详细]
  • 观察 | 求职体验:收到录用通知的公司通常不深究技术细节,而那些详细追问的公司往往没有后续进展
    观察 | 求职体验:收到录用通知的公司通常不深究技术细节,而那些详细追问的公司往往没有后续进展 ... [详细]
author-avatar
所谓-旧
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有