频道栏目
首页 > 程序开发 > 移动开发 > 其他 > 正文
关闭mono的GC,防止其带来的卡顿
2017-07-20 09:36:22         来源:Per Pixel Lighting  
收藏   我要投稿

我们的游戏品类特殊,对游戏对局内的画面流畅性要求极高。不允许出现可以明显察觉的卡顿。当我们解决了所有对象创建,JIT编译等带来的卡顿之后。还有一个较为棘手的卡顿来源就是GC。我们想了各种办法尽可能的减少对局内的内存分配。包括对UI的特殊处理,对网络消息的特殊处理。最后终于能够做到在一个对局之内不会产生GC。
但是,我们知道,这件事并不是一劳永逸的。随着关卡的继续开发,总有一天还会出现GC,有些内存分配是没办法彻底消除的,比如UI上变化的文字。因此我决定去搞mono本身。
首先是编译mono,这方面教程很多,比如【1】。然后就是设法开关GC,事实上mono内部有这样的功能函数,GC_enable和GC_disable,我们要做的不过是将这些符号导出。mono\mini\ldscript文件中描述了mono lib的导出符号,在其中增加GC_enable和GC_disable,重新编译,得到改造过的libmono.so。替换unity目录下的libmono(需要区分armv7和x86)
在C#中实现一个功能类,然后就可以愉快的开关GC功能了。

class GarbageCollection
{
#elif UNITY_ANDROID
    [DllImport("mono")]
    protected static extern void GC_enable();
    [DllImport("mono")]
    protected static extern void GC_disable();
#else
    protected static void GC_enable()
    {
    }
    protected static void GC_disable()
    {
    }
#endif
}

那么IOS平台呢,本来想使用跟android平台类似的方法。后来发现由于IOS上使用IL2CPP,mono被改造后集成进了libiPhone.a,同时大量符号都被导出了
包括GC_enable和GC_disable,也就是说在IOS上我们可以直接使用这两个接口,编译时不会遇到任何问题。
最后,我们的功能类就是这个样子

class GarbageCollection
{
    static bool enabled = true;
    public static bool Enable
    {
        get
        {
            return enabled;
        }
        set
        {
            if (value == enabled)
            {
                return;
            }
            if (value)
            {
                try
                {
                    GC_enable();
                }
                catch (System.Exception ex)
                {
                    Debug.Log("GC exception!");
                    Debug.Log(ex.ToString());
                }
            }
            else
            {
                try
                {
                    GC_disable();
                }
                catch (System.Exception ex)
                {
                    Debug.Log("GC exception!");
                    Debug.Log(ex.ToString());
                }
            }
            enabled = value;
        }
    }
#if UNITY_IPHONE
   
    [DllImport ("__Internal")]
    protected static extern void GC_enable();
    [DllImport ("__Internal")]
    protected static extern void GC_disable();
#elif UNITY_ANDROID
    [DllImport("mono")]
    protected static extern void GC_enable();
    [DllImport("mono")]
    protected static extern void GC_disable();
#else
    protected static void GC_enable()
    {
    }
    protected static void GC_disable()
    {
    }
#endif
}

做个简单的测试,在update里面不断的分配内存,很高兴的看到内存在飙涨。(这话怎么感觉怪怪的)


点击复制链接 与好友分享!回本站首页
上一篇:AbstractQueuedSynchronizer(AQS)源码解析
下一篇:React Native自定义控件【底部抽屉菜单】
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站