Unity慢吗? 小心LINQ

人们常说Unity很慢。 但是多少钱? 我正在开发Pixel Studio应用程序,这是一个像素艺术编辑器。 我为他写了GIF格式的实现。 最耗时的操作是GIF编码,即LZW压缩算法。 让我们看看Unity如何处理这个问题。

图片

首先,我将立即阐明为什么我必须编写自己的库。 是的,一切都很简单,包含精美的GifBitmapEncoder的System.Windows.Media.Imaging库无法连接到Unity。 因此,我在中心上阅读了有关GIF的文章,采用了规范,并用二十一点制作了我的GIF。

当然,我开始在控制台应用程序的Visual Studio中编写和调试该库。 我会忽略这一刻,这很无聊,而且调试很长,花了3天的时间。 在这种算法中,我没有经验,通常是做游戏。 好的,图书馆已经准备好了。 例如,一个200帧的测试“沉重” GIF和256x256的分辨率可以在15秒内编码(当然,Ryzen 7在我的硬件上)。 我想了很多,用绅士的手使压缩过程并行化(就像Unity应该支持线程一样)。 测试GIF在5秒内被编码。 太好了!

只需将所有源代码复制到Unity中以检查其是否有效。 测试GIF编码需要120秒。 在多线程模式下(是的,Unity中的线程正常工作,主要是不触摸UI),对gif进行编码需要180秒。 Facepalm。

Google-事实证明,这个问题很普遍。 根据类似的报告,Unity中的算法代码运行速度要慢10到20倍。 据称这与另一个垃圾回收实现和模糊的Editor Overhead有关。 在程序集(Windows,Android)中,情况类似。 例如,在.exe程序集中,它的工作速度略微提高了20%。

给读者的问题-我是在做错什么,还是有问题?

链接到感兴趣的GIF实施: GitHub 。 该库是使用C#版本6和.NET 3.5编写的,以便与Unity的较早版本兼容。 可以将项目切换到.NET 4.0,然后ThreadPool将运行得更快。

UPD:感谢您的评论! 一切都变得有些混乱:两个带锁的线程和一个曲线实现。 所以我准备了一个简单的案例-通过LINQ中的数组运行的操作。 即,在LZW压缩期间执行这样的操作(仅在字典中进行键检查)。

图片

我们在控制台应用程序中执行-5毫秒。
在Unity中运行-2100毫秒。

UPD:部分问题可在LINQ中找到。 例如,调用Contains比Array.IndexOf慢几倍。 LINQ很棒,它可以节省时间并使代码更漂亮。 但是,在诸如处理大型对象的应用任务中则不然。 这适用于Unity中的特定LINQ实现。

UPD:优化了LZW压缩算法,删除了字典中的字符串键。 尽可能删除LINQ以进行大集合。 我没有涉及多线程的实现。 一切都飞起来,甚至在Android上也是如此。 当然,控制台应用程序的速度之间的差异仍然存在,但并不是那么明显。

特别感谢WNeZRoS在优化代码方面的帮助以及所有参与讨论的人员! 尽管LINQ中的制动原因仍未解决。

Source: https://habr.com/ru/post/zh-CN415923/


All Articles