H5动态加载dragonBones卸载时内存泄露

遇到一个内存问题 dragonBones相关的
我使用cc.loader.loadResDir 加载了20个角色
加载前chrome内存管理器显示 GPU显存60MB
加载后GPU 180MB左右,releaseResDir之后内存还原至60MB
重复多次未见内存泄露

然而当我加载dragonBones并添加ArmatureDisplay至node节点
并正确设置armatureName后节点可以显示动画
但之后反复destroy/releaseResDir显存会不断上升至约泄露60MB
(未设置armatureName时其值为空’’,动画不显示,内存也不泄露)

另外dragonBones.CCFactory.getFactory().clear()方法每次都报错!(dispose那里报错)
想问下动态加载的dragonBones如何正确卸载,内存真的爆了爆了

脚本创建dragonBones动态的方法如下(参考http://forum.cocos.com/t/topic/41362/2)

cc.loader.loadResAll('db', function (err, assets) {
    let node = new cc.Node('1213');
    self.node.addChild( node, 99999 );
    node.setPosition( cc.p( 200, 200 ) );
    let armatureDisplay = node.addComponent(dragonBones.ArmatureDisplay);

    for ( let i = 0; i < assets.length; i++ ) {
        if (assets[i] instanceof dragonBones.DragonBonesAsset) {
            armatureDisplay.dragonAsset = assets[i];
        }

        if (assets[i] instanceof dragonBones.DragonBonesAtlasAsset) {
            armatureDisplay.dragonAtlasAsset = assets[i];
        }
    }
    armatureDisplay.armatureName = 'mecha_1502b';
    armatureDisplay.playAnimation('idle', -1);
});

版本是1.5.1

麻烦提交一个 demo?

以creator官方demo里面的dragonbones资源为例子

var create = function (path, name /*= ""*/, times /*= null*/, callback /*= undefined*/, speed) {
    var subPath = path.split("/");
    var nodeName = subPath.length > 0 ? subPath[subPath.length - 1] : path;
    var node = new cc.Node(nodeName);

    cc.loader.loadResDir(path, function (err, assets) {


        var armatureDisplay = node.addComponent(dragonBones.ArmatureDisplay);
        for (var i = 0; i < assets.length; i++) {
            if (assets[i] instanceof dragonBones.DragonBonesAsset) armatureDisplay.dragonAsset = assets[i];
            if (assets[i] instanceof dragonBones.DragonBonesAtlasAsset) armatureDisplay.dragonAtlasAsset = assets[i];
        }

        // display 加载完毕
        cc.log("ANI.create", path, name, armatureDisplay.getArmatureNames(), new Date().valueOf());

            node.display = armatureDisplay;
            armatureDisplay.armatureName = 'mecha_1502b';

        
    });

    return node;
};

脚本创建之后执行以下两条语句卸载

node.destroy()
cc.loader.releaseResDir('dragonbones')

并不能还原内存(会有一部分泄漏)

经调试可以发现
armatureDisplay.armatureName = 'mecha_1502b';
若不执行该语句,动画不能正常显示内存也可以完全释放
而执行之后,内存会涨的更多一些,同时也无法完全释放!

demo中的动画尺寸太小了500*500左右大概不到1MB显存,很不明显

我们自己的游戏中20个角色
若不设置armatureDisplay.armatureName
大概内存从60上涨至160
反复加载卸载N次基本都能回到60,5MB以内波动,绝对不超过65MB

然而设置了armatureDisplay.armatureName = 'idle'//xxx动作名
动画可以显示了
内存第一次大概从60上涨至170左右,反正要多一点
反复卸载内存越来越多,大概是60-65-70-80-90…120这个水平
到了120以后继续反复卸载了几次好像不会无限上涨了…

参考的始终是Chrome进程管理中的显存这一块
实际游戏中很容易产生上百兆的内存泄漏
目前dragonBones卸载会产生这样的内存问题
而音频文件也没法release,所有播过的声音不能移出内存(http://forum.cocos.com/t/h5/49874/2)?
这样的内存消耗太大

不论是引擎问题还是用户使用方式不当
都希望开发者可以指条明路,重视这些基础问题
谢谢啦

又调了一遍dragonBones的资源加载卸载内存问题
发现PC浏览器和手机浏览器也是有区别的

PC chrome上面 loadResDir 加载20个龙骨 理论纹理是70MB(每个角色约1024*1024)
反复loadResDir/releaseResDir 内存看不到明显泄露

手机QQ浏览器这样做,反复几次很快就可以泄露100~200MB
都是只加载卸载,不做显示操作

ccc1.5.1 db导出4.5

cc.loader.loadResDir(url)
cc.loader.releaseResDir(url , cc.Texture2D)
这样调用首次加载龙骨纹理、数据
卸载时仅卸载龙骨纹理
再次加载时只会加载纹理
在手机浏览器测试加载70MB龙骨纹理
加载卸载内存变化如下
360-470-400-470-(400-470)*
趋于稳定

基本可以确定试图释放全部龙骨资源时
cc.loader.releaseResDir(url)会存在内存泄露(手机浏览器)

测试环境手机qq浏览器
引擎组有空修复一下吧

你反馈的第一个 GPU 会持续上升的问题,我重现不了。麻烦你提交一个项目给我测试看看。谢谢!

这个案例能发给我看看吗?

前面不是说了会有 GPU 显存泄露吗,怎么这里又说不会了……

例子我现在没法提供我这边的资源都是内网商业项目

我说的有点乱,但没有自相矛盾的地方,我解释一下

1.PC Chrome GPU内存疑似泄露
loadResDir(url)
loadCallBack中设置armatureDisplay.armatureName = ‘idle’
releaseResDir(url)
反复以上操作

2.手机qq浏览器内存疑似泄露
loadResDir(url)
releaseResDir(url)
反复以上操作

3.勉强解决方案
loadResDir(url)
releaseResDir(url)
反复以上操作
dragonBones使用的纹理可以正常加载卸载
其余动画数据常驻内存

我使用 Chrome 的 Memory 调试工具,并未看到有内存泄露。不然你扣一个 demo 出来吧,不要用公司资源。