C#Unity框架

自己实现一个零GC的高效率协程

Spread the love

随着代码越来越趋向于响应式,协程的使用也慢慢增多,协程带来的消耗也变得不容忽视了。

在AssetStore上有一个插件More Effective Coroutine,其效率比Unity原生的Coroutine要快上20倍,我自己也验证过了。于是我也自己实现了一套高效率的协程工具。

如果只想了解用的话直接跳转到使用方法就可以了。

下面进行测试:

开启10w个协程,每一个协程都每一帧进行自增。

协程内容大概如下。

我先运行了MEC,而后是我的ReCoroutine,最后是Unity原生的Coroutine。

数据分析:

Profiler上的显示如下:

可以明显看到MEC的效率非常高,我的跑起来稍微有点吃力,而原生的协程已经爆炸了。

具体的参数可以看一下:

这是MEC的数据:耗时11ms

这是ReCoroutine的数据:耗时36ms

最后是原生Coroutine的数据:耗时200ms

其中overhead是内部的代码,无法查看其细节。

为什么相差能够这么大呢。

原本,我以为相差如此之大的原因是因为协程未放入Update中,其实并非是这样。

因为原生的Coroutine的调用频率与自己实现的调用频率并没有太大的差别。

其中的原因在迭代器之中,MEC与ReCoroutine的迭代器是一数字进行返回的,而原生的迭代器则是返回了Unity自己定义的Yield类型。

每次返回的时候通常需要new一个新的对象,造成了大量的GC。其内部实现的消耗也占了很大一部分。

而MEC与ReCoroutine则是完全返回了float,并且避免了装箱与拆箱带来的巨大消耗。

使用方法

其中yield return后面的数字代表等待的时间,如果不等待则直接返回0就可以了。

那如果我们需要等待WWW呢,ReCoroutine已经提供了这个功能。

你可以自定义任何你想要的条件来进行等待:

ReCoroutine协程管理器

在之前我们有对原生的协程进行封装,编写了协程管理器。现在也同样的,我们对ReCoroutine进行封装,编写了协程管理器。

可以对协程进行启动、暂停、重启,以及一些快捷函数。

它能够帮助我们更好地对协程进行操作与把控。

对原生协程的优化

不过很多时候可能大家还是不习惯使用新的协程。

原生协程也不是没有优化的办法。

在这次更新中,加入了CoroutineConst,其中包含了所有Yield结构的常量进行了保存,

在使用的时候尽量使用已经定义的常量而不是new一个新的对象会在频繁的yield中省下大量的GC。

如上图所示。

One thought on “自己实现一个零GC的高效率协程

发表评论

电子邮件地址不会被公开。 必填项已用*标注