03. 协程

作者: Wenchao | 来源:发表于2017-08-31 20:34 被阅读87次

    这是摘自Unity官方文档有关优化的部分,原文链接:https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity.html
    总共分为如下系列:

    1. 采样分析
    2. 内存部分
    3. 协程
    4. Asset审查
    5. 理解托管堆 【推荐阅读】
      5.1 上篇:原理,临时分配内存,集合和数组
      5.2 下篇:闭包,装箱,数组
    6. 字符串和文本
    7. 资源目录
    8. 通用的优化方案
    9. 一些特殊的优化方案

    协程的执行过程和其他的脚本代码不同。大部分的脚本代码在性能日志中只会出现在某个特定的Unity回调之下。然而,协程的CPU记录会在日志中出现两次。

    协程中的第一部分的代码,从协程方法的开始到第一个yield返回的部分,会出现在协程开始执行的日志中。通常情况下,会出现在StartCoroutine方法被调用的地方。Unity生命周期方法回调产生的协程会对应出现在这些Unity方法对应的C++代码的回调之下。

    剩下的协程的代码,从第一次返回yield直到最后完成执行的时候—会出现在Unity主循环的DelayedCallManager方法下面。

    协程会被C#编译器生成一个类的实例所持有。这个对象需要在协程多次被调用的时候跟踪协程的状态。因为协程的局部变量必须yield调用中保存,这些局部变量被放入到生成的类中,所以在协程执行的过程中,这些变量一直都在都在堆中。这个对象也会追踪协程的内部状态:它会记住协程在什么时候从Yield状态切换到Resume状态。

    所以,开启协程对内存的影响是固定的开销加上局部变量的大小。

    开启协程的代码会创建并且调用这个对象,然后Unity的DelayedCallManager会在协程Yield条件被满足的时候再次进行调用这个对象。因为协程通常会在其他协程的外部执行,所以它们执行的开销通常在上面的两个位置中。

    协程的回调日志

    上面的截图展示了这种情况,DelayedCallManager恢复了几个不同协程的运行:PopulateCharacters,AsyncLoad和LoadDatabase等。

    当条件允许的时候,最好使用尽可能少的协程去完成需求。虽然嵌套的协程对代码的清晰度和可维护性非常好,但是内存的开销会比较高,因为需要生成跟踪协程的对象的开销。

    如果某个协程差不多每帧都要运行,而且很长时间都不通过Yield返回,为了可读性最好还是用Update或者LateUpdate替代。对于长时间运行或者无限循环的协程更是如此。

    必须要记住协程不是线程。协程内部的同步性的操作是在主线程内完成的。如果需要减少花在主线程的CPU开销,对协程的优化也和其他脚本代码一视同仁。

    协程对于耗时比较长的异步操作非常有用,例如等待HTTP传输,Asset加载和文件I/O操作完成。

    上篇: 内存分析

    下篇:资源审查

    如果觉得文章对您有用,请点个赞呗!☺☺☺

    相关文章

      网友评论

        本文标题:03. 协程

        本文链接:https://www.haomeiwen.com/subject/ttecjxtx.html