axmolengine / axmol

Axmol Engine – A Multi-platform Engine for Desktop, XBOX (UWP) and Mobile games. (A fork of Cocos2d-x-4.0)
https://axmol.dev
MIT License
922 stars 205 forks source link

Node:getChildren()性能问题 #2068

Closed qq461787436 closed 3 months ago

qq461787436 commented 3 months ago

试例代码如下:

for _playindex=1, 5, 1 do
    local _Node = ccui.Layout:create()
    _Node:setContentSize(cc.size(50, 200))
    _Node:setPosition(cc.p(55*_playindex,0))
    _Node:setAnchorPoint(CWPointMake(0,0))
    self:addChild(_Node)

    for _i=1, 10, 1 do
        local _FileName = "DefaultRes_Icon.png"
        local _GradeSp = cc.Sprite:createWithSpriteFrameName(_FileName)
        _Node:addChild(_GradeSp)
        _GradeSp:setTag(_i)
        _GradeSp:setPosition(CWPointMake(25, #_Node:getChildren()*25))
    end

    local _ASpeed = 100
    local _CurSpeed = 0
    local _MaxSpeed = 200
    local _GradeHight = 100/3
    local _StopActIndex = 0
    local _LostTime = 0
    cc.Director:getInstance():getScheduler():scheduleScriptFunc(function(_dt)
        _LostTime = _LostTime + _dt

        local _CurNodePtY = _Node:getPositionY()
        _CurNodePtY = _CurNodePtY-_dt*_CurSpeed
        _Node:setPositionY(_CurNodePtY)

        _CurSpeed = _CurSpeed+_dt*_ASpeed
        if _CurSpeed > _MaxSpeed then
            _CurSpeed = _MaxSpeed
        end

        if math.abs(_CurNodePtY)>_GradeHight then
            local _Children = _Node:getChildren()
            _Node:setPositionY(0)
        end
    end, 0, false)
end

QQ20240803-114830

程序满帧率被设置成60 运行上面代码帧率在50左右,注释掉 local _Children = _Node:getChildren() 帧率可以保持在60 有没有知道如何优化的

rh101 commented 3 months ago

Have you tried running the Time Profiler Instrument in Xcode to find out what section of code is causing the performance issue?

qq461787436 commented 3 months ago

I tried runing it, the result is shown in the figure QQ20240805-160825

rh101 commented 3 months ago

I'm not sure what that LUA method does, but perhaps someone else with knowledge can help with this.

A possibly work-around is if you keep track of the children outside of that scheduled method, you wouldn't need to call _Node:getChildren() on every loop.

Also, which version of Cocos2d-x are you comparing Axmol to? v3.17, or v4?

Other than that, I'm curious about this section of code (check the comment please):

    cc.Director:getInstance():getScheduler():scheduleScriptFunc(function(_dt)
        _LostTime = _LostTime + _dt

        local _CurNodePtY = _Node:getPositionY()
        _CurNodePtY = _CurNodePtY-_dt*_CurSpeed
        _Node:setPositionY(_CurNodePtY)  --> Y is set here, but then it is also set below again to 0 if the condition is met

        _CurSpeed = _CurSpeed+_dt*_ASpeed
        if _CurSpeed > _MaxSpeed then
            _CurSpeed = _MaxSpeed
        end

        if math.abs(_CurNodePtY)>_GradeHight then
            local _Children = _Node:getChildren()
            _Node:setPositionY(0)
        end
    end, 0, false)

Would this be better:

    cc.Director:getInstance():getScheduler():scheduleScriptFunc(function(_dt)
        _LostTime = _LostTime + _dt

        local _CurNodePtY = _Node:getPositionY()
        _CurNodePtY = _CurNodePtY-_dt*_CurSpeed

        _CurSpeed = _CurSpeed+_dt*_ASpeed
        if _CurSpeed > _MaxSpeed then
            _CurSpeed = _MaxSpeed
        end

        if math.abs(_CurNodePtY)>_GradeHight then
                        local _Children = _Node:getChildren()
            _Node:setPositionY(0)
                else
                        _Node:setPositionY(_CurNodePtY) 
        end
    end, 0, false)
qq461787436 commented 3 months ago

用于测试,写的有点不严谨 我还测试了下lua对table的循环遍历,性能上也很差,貌似都消耗在static lu_mem propagatemark (global_State *g) 这个函数里 测试代码如下(直接复制就可以运行):

function PrintObj(_value)
    local tv = ""
    local xn = 0

    local function tvlinet(xn)
        for i=1, xn do
            tv = tv.."    "
        end
    end

    local function LogString(lv)
        local _lt = type(lv)

        if lv == nil then
            return "nil"
        elseif _lt == "string" then
            return string.format("\"%s\"", lv)
        elseif _lt == "number" then
            return string.format("[%s]", tostring(lv))
        elseif _lt == "boolean" then
            return string.format("<%s>", lv)
        else
            return string.format("<%s>", _lt)
        end
    end

    local function printTab(k,v)
        if type(v) == "table" then
            --输出table键值
            tvlinet(xn)
            tv = tv..LogString(k)..":\n"

            tvlinet(xn)
            tv = tv.."{\n"
            xn = xn + 1
            --输出下一个键值
            for _vk, _vv in pairs(v) do
                printTab(_vk, _vv)
            end
            --输出结束符号
            xn = xn - 1
            tvlinet(xn)
            tv = tv.."}\n"
        else
            --输出值
            tvlinet(xn)
            tv = tv..LogString(k)..":"..LogString(v).."\n" 
        end
    end

   for i=1, #_value do
        local _LogV = _value[i]

        if type(_LogV) == "table" then 
            xn = xn + 1
            tv = tv.."\n{\n"
            for _vk, _vv in pairs(_LogV) do
                printTab(_vk, _vv)
            end
            tv = tv.."}\n"
        else
            tv = tv..LogString(_LogV)
        end
    end

    print(tv)
end

local _table = {
    test1=0,
    test2=false,
    test3=-123,
    test4=123,
    test5=123.123,
    test6=-123.123,
    test7=77.77,
    test8=-77.77,
    testmap={
        name="sdfsf",
        test=23.234,
        test2={1,2,4,6,7,8,345,56.77,{1,2,3,4}},
        test3="asdfkjsdlkfgj",
        test4={test1={234234,333}, 2,4,5,6},
        test5={123,23434, test1={234234,333}, 2,4,5,6},
        test6={123,23434,2,4,5,6,test1={234234,333}},
    }
}

for _playindex=1, 10, 1 do
    Obj({_table})
end

axmol lua 2.1.4 消耗了2.92s,用cocos2d lua 4.0版本消耗0.07s,这两个运行环境是一样但差距有点大呀,能力有限有没有大神看看哪里出问题了?

halx99 commented 3 months ago

https://github.com/axmolengine/axmol/issues/332, maybe GC 模式设置错误,请检查下

qq461787436 commented 3 months ago

以前的项目修改了GC模式,现在项目迁移,没发现这个还能导致性能问题 在启动lua的时候设置 collectgarbage("setpause", 100) collectgarbage("setstepmul", 5000) 去掉,问题一下子解决了 非常感谢