В моей карте один единственный триггер вызывается каждый раз при получении юнитом урона и, следовательно, 90% утечек происходит из за этого триггера.
Прошу мастеров оптимизации разобраться, в каком именно месте создаются утечки?
код jass (SDMS триггер)
//set Color[0] = "|c00FF0303"//Игрок 1(красный)
//set Color[1] = "|c000042FF"//и по порядку...
//set Color[2] = "|c001CE6B9"
//set Color[3] = "|c00540079"
//set Color[4] = "|c00FFFC01"
//set Color[5] = "|c00FE8A0E"
//set Color[6] = "|cff00ff00"
//set Color[7] = "|c00E55BB0"
//set Color[8] = "|c00959697"
//set Color[9] = "|c007EBFF1"
//set Color[10] = "|c00106246"
//set Color[11] = "|c004E2A04"
//set Color[12] = "|c00282828"// \
//set Color[13] = "|c00282828"// >>Три нейтральных игрока
//set Color[14] = "|c00282828"// /
//========================================
//----------цветовые переменные-----------
//========================================
function SDMSTextVars takes integer PlayerNumber returns string
    local string array Color
    set Color[0] = "|cffffa500"//Игрок 1(красный)
    set Color[1] = "|cffffa500"//и по порядку...
    set Color[2] = "|cffffa500"
    set Color[3] = "|cffffa500"
    set Color[4] = "|cffffa500"
    set Color[5] = "|cffffa500"
    set Color[6] = "|cffffa500"
    set Color[7] = "|cffffa500"
    set Color[8] = "|cffffa500"
    set Color[9] = "|cffffa500"
    set Color[10] = "|cffffa500"
    set Color[11] = "|cffffa500"
    set Color[12] = "|cff9db9eb"// \
    set Color[13] = "|cff9db9eb"// >>Три нейтральных игрока
    set Color[14] = "|cff9db9eb"// /
    return Color[PlayerNumber]
endfunction
//========================================
//---------Возвращаемые значения----------
//========================================
function SDMSFontSize takes nothing returns real
    return 10.0//Размер шрифта, которым будут писаться плавающие строки. Не ставить слишком маленький, т.к. не будет видно. Рекомендую 10-15 пунктов.
endfunction
function SDMStheTrigger takes nothing returns trigger
    return udg_SDMStrigger//Здесь название любой простой глобальной переменной типа триггер.
endfunction
function SDMSLifeTime takes nothing returns real
    return 1.0//Время продолжительности строки. Большой не ставить, т. к. будет лагать. Рекомендую 1-2 секунды.
endfunction
function SDMSLifeTimeSecondary takes nothing returns real
    return 2.0//Дополнительное время продолжительности жизни строки. Не ставить меньше, чем основное, но чем меньше это значение, тем меньше утечка памяти. Рекомендую 120-200% от основного времени.
endfunction
function SDMSMinus takes nothing returns string
    return "-"//Возвращает то, что стоит перед числом нанесённого урона. Примеры:
//"Нанесено " например: Нанесено 15
//"Получено " например: Получено 21
//""          например: 16
//Рекомендую использовать "-" из-за большей производительности
endfunction
function SDMSPlus takes nothing returns string
    return ""//Возвращает то, что стоит перед числом нанесённого урона. Примеры:
//" ед. урона"         например: 15 ед. урона
//" очков повреждения" например: 21 очков повреждения
//Рекомендую использовать "" из-за большей производительности. Комбинируя функции Minus и Plus, можно добиваться отличных результатов. Например: Нанесено 17 ед. урона.
endfunction
//========================================
//----Постоянные функции - не изменять!---
//========================================
function SDMSCreateTextTag takes nothing returns nothing
    local unit u=GetTriggerUnit()
    local unit s=GetEventDamageSource()
    local player pl=GetOwningPlayer(u)
    local player pl2=GetOwningPlayer(s)
    local integer i=GetConvertedPlayerId(pl)
    local texttag tt=null
    local real fontSize=SDMSFontSize()
    local real lifeTime=SDMSLifeTime()
    local real lifeTime2=SDMSLifeTimeSecondary()
    local real dmg=GetEventDamage()
    local string minus=SDMSMinus()
    local string plus=SDMSPlus()
    local string textColor=SDMSTextVars(i-1)
    local boolean b
    local location l
    
    if ( pl2 == Player(PLAYER_NEUTRAL_AGGRESSIVE) and udg_Players > 1) then
        set dmg = dmg + dmg*(udg_Players-1)*0.25
        if ( GetUnitStateSwap(UNIT_STATE_LIFE, u) <= dmg*(udg_Players-1)*0.25 ) then
            call SetUnitState(u, UNIT_STATE_LIFE, 1.00)
        else
            call SetUnitState(u, UNIT_STATE_LIFE, ( GetUnitStateSwap(UNIT_STATE_LIFE, u) - ( dmg*(udg_Players-1)*0.25 ) ))
        endif
    endif
    if ( dmg > 1.00 ) and ( dmg < 9999.00 ) then
        set tt = CreateTextTag()
        call SetTextTagText(tt, textColor+minus+I2S(R2I(dmg))+plus+"|r", TextTagSize2Height(fontSize))
        call SetTextTagPosUnit(tt, u, 0)
        call SetTextTagColor(tt, 255, 255, 255, 255) 
        call SetTextTagVelocity(tt, TextTagSpeed2Velocity(96.0) * Cos(90 * bj_DEGTORAD), TextTagSpeed2Velocity(96.0) * Sin(90 * bj_DEGTORAD))
        call SetTextTagPermanent(tt, false)
        call SetTextTagLifespan(tt, lifeTime)
        call SetTextTagFadepoint(tt, 0.0)
    endif
    //эффекты брызг крови
    if (  dmg >= ( GetUnitState(u, UNIT_STATE_MAX_LIFE) * 1.0 )) then
        call DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Human\\HumanLargeDeathExplode\\HumanLargeDeathExplode.mdl", u, "chest"))
    else
        if (  dmg >= ( GetUnitState(u, UNIT_STATE_MAX_LIFE) * 0.33 )) then
            call DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl", u, "chest"))
        else
            if (  dmg >= ( GetUnitState(u, UNIT_STATE_MAX_LIFE) * 0.2 )) then
                call DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Critters\\Albatross\\CritterBloodAlbatross.mdl", u, "chest"))
            endif
        endif
    endif
    //Отлов урона
    if GetUnitTypeId(s) == 'u026' then //Прорубающая Атака мастера меча
        set s = gg_unit_Nbbc_0091
        if ( GetUnitAbilityLevelSwapped('A06B', s) > 0 ) then
            if ( GetRandomInt(1, 100) <= udg_Hero_Might_Chance[GetConvertedPlayerId(GetOwningPlayer(s))] or udg_Rune2[GetConvertedPlayerId(GetOwningPlayer(s))] == 1 ) then
                if ( GetRandomInt(1, 100) <= 3 + GetUnitAbilityLevelSwapped('A06B', s) ) then
                    set l=GetUnitLoc(u)
                    call DummyCastUnit( GetOwningPlayer(s), l, 0.5, 'A045', 1, "bloodlust", s )
                    call RemoveLocation(l)
                endif
            endif
            if ( GetRandomInt(1, 100) <= udg_Hero_Spirit_Chance[GetConvertedPlayerId(GetOwningPlayer(s))] or udg_Rune2[GetConvertedPlayerId(GetOwningPlayer(s))] == 2 ) then
                if ( (GetRandomInt(1, 100) <= udg_Hero_Might_Chance[GetConvertedPlayerId(GetOwningPlayer(s))] or udg_Rune1[GetConvertedPlayerId(GetOwningPlayer(s))] == 1) and GetRandomInt(1, 100) <= 35 ) then
                    call SetUnitState(s, UNIT_STATE_LIFE, ( GetUnitStateSwap(UNIT_STATE_LIFE, s) + I2R(GetHeroAgi(s, true)) * ( 0.04 + ( 0.04 * I2R(GetUnitAbilityLevelSwapped('A06B', s)) ) ) ) )
                else
                    call SetUnitState(s, UNIT_STATE_LIFE, ( GetUnitStateSwap(UNIT_STATE_LIFE, s) + I2R(GetHeroAgi(s, true)) * ( 0.02 + ( 0.02 * I2R(GetUnitAbilityLevelSwapped('A06B', s)) ) ) ) )
                endif
                call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\VampiricAura\\VampiricAuraTarget.mdl",  s, "chest"))
            endif
            if ( GetRandomInt(1, 100) <= udg_Hero_Grow_Chance[GetConvertedPlayerId(GetOwningPlayer(s))] or udg_Rune2[GetConvertedPlayerId(GetOwningPlayer(s))] == 3 ) then
                call DisableTrigger( GetTriggeringTrigger())
                if ( (GetRandomInt(1, 100) <= udg_Hero_Might_Chance[GetConvertedPlayerId(GetOwningPlayer(s))] or udg_Rune1[GetConvertedPlayerId(GetOwningPlayer(s))] == 1) and GetRandomInt(1, 100) <= 35 ) then
                    call DamageArea (s, GetUnitX(u), GetUnitY(u), 200, I2R(GetHeroAgi(s, true)) * ( 0.2 + ( 0.2 * I2R(GetUnitAbilityLevel(s,'A06B')) ) ), ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL)
                else
                    call DamageArea (s, GetUnitX(u), GetUnitY(u), 200, I2R(GetHeroAgi(s, true)) * ( 0.1 + ( 0.1 * I2R(GetUnitAbilityLevel(s,'A06B')) ) ), ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL)
                endif
                call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl",  u, "chest"))
                call EnableTrigger( GetTriggeringTrigger())
            else
                call DisableTrigger( GetTriggeringTrigger())
                if ( (GetRandomInt(1, 100) <= udg_Hero_Might_Chance[GetConvertedPlayerId(GetOwningPlayer(s))] or udg_Rune1[GetConvertedPlayerId(GetOwningPlayer(s))] == 1) and GetRandomInt(1, 100) <= 35 ) then
                    call UnitDamageTarget(s, u, I2R(GetHeroAgi(s, true)) * ( 0.2 + ( 0.2 * I2R(GetUnitAbilityLevel(s,'A06B')) ) ), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                else
                    call UnitDamageTarget(s, u, I2R(GetHeroAgi(s, true)) * ( 0.1 + ( 0.1 * I2R(GetUnitAbilityLevel(s,'A06B')) ) ), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                endif
                call EnableTrigger( GetTriggeringTrigger())
            endif
        endif
        if ( (GetRandomInt(1, 100) <= udg_Hero_Might_Chance[GetConvertedPlayerId(GetOwningPlayer(s))] or udg_Rune1[GetConvertedPlayerId(GetOwningPlayer(s))] == 1) and GetRandomInt(1, 100) <= 35 ) then
            call DisableTrigger( GetTriggeringTrigger())
            call UnitDamageTarget(s, u, 50 + ( 25 * I2R(GetUnitAbilityLevelSwapped('A0A9', s)) ), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
            call EnableTrigger( GetTriggeringTrigger())
        endif
        if ( GetRandomInt(1, 100) <= udg_Hero_Spirit_Chance[GetConvertedPlayerId(GetOwningPlayer(s))] or udg_Rune1[GetConvertedPlayerId(GetOwningPlayer(s))] == 2 ) then
            set l=GetUnitLoc(u)
            if ( GetRandomInt(1, 100) <= udg_Hero_Grow_Chance[GetConvertedPlayerId(GetOwningPlayer(s))] or udg_Rune2[GetConvertedPlayerId(GetOwningPlayer(s))] == 3 ) then
                call DummyCastUnit(GetOwningPlayer(s),l,0.5,'A0IK',2,"acidbomb",u)
            else
                call DummyCastUnit(GetOwningPlayer(s),l,0.5,'A0IK',1,"acidbomb",u)
            endif
            call RemoveLocation(l)
        endif
    endif
    //эффекты предметов
    if (GetUnitAbilityLevel(u, 'B02S') > 0) then
        call SetUnitState(u, UNIT_STATE_LIFE, ( GetUnitState(u, UNIT_STATE_LIFE) + dmg * 2.00 ))
    endif
    if (GetUnitAbilityLevel(u, 'B01L') > 0) then
        call SetUnitState(s, UNIT_STATE_MANA, ( GetUnitState(s, UNIT_STATE_MANA) + 6.00 ))
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Items\\AIma\\AImaTarget.mdl", s, "overhead"))
    endif
    if (GetUnitAbilityLevel(u, 'B01K') > 0) then
        call SetUnitState(s, UNIT_STATE_MANA, ( GetUnitState(s, UNIT_STATE_MANA) + 20.00 ))
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Items\\AIma\\AImaTarget.mdl", s, "overhead"))
    else
        if (GetUnitAbilityLevel(u, 'B01E') > 0) then
            call DisableTrigger( GetTriggeringTrigger() )
            call UnitDamageTarget(s, u, I2R(GetHeroAgi(s, true)), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)
            call EnableTrigger( GetTriggeringTrigger() )
        else
            if (GetUnitAbilityLevel(u, 'B01G') > 0) then
                call DisableTrigger( GetTriggeringTrigger() )
                call UnitDamageTarget(s, u, ((GetUnitX(u)-GetUnitX(s))*(GetUnitX(u)-GetUnitX(s)) + (GetUnitY(u)-GetUnitY(s))*(GetUnitY(u)-GetUnitY(s)))*0.2, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)
                call EnableTrigger( GetTriggeringTrigger() )
            endif
        endif
    endif
    if ( GetUnitAbilityLevel(u, 'B02O') > 0 or GetUnitAbilityLevel(u, 'B02N') > 0 ) then
        set udg_FireBlades_Target = u
        call CreateUnit( pl2, 'u00W', GetUnitX(u), GetUnitY(u), bj_UNIT_FACING )
    endif
    if (GetUnitAbilityLevel(u, 'B03M') > 0) then
        if ( dmg > 50.00 ) then
            call SetUnitState(u, UNIT_STATE_LIFE, ( GetUnitState(u, UNIT_STATE_LIFE) + 50.00 ))
        else
            call SetUnitState(u, UNIT_STATE_LIFE, ( GetUnitState(u, UNIT_STATE_LIFE) + dmg ))
        endif
    endif
    //
    call PolledWait(lifeTime2)

    set u=null
    set s=null
    set pl=null
    set pl2=null
    set l=null
    set i=0
    set fontSize=0
    set lifeTime=0
    set lifeTime2=0
    set dmg=0
    set minus=""
    set plus=""
    set textColor=""
    call DestroyTextTag(tt)
    set tt=null

endfunction
function SDMSTriggerRegisterUnitDamaged takes nothing returns nothing
    call TriggerRegisterUnitEvent(SDMStheTrigger(),GetEnteringUnit(),EVENT_UNIT_DAMAGED)
endfunction
function SDMSGroupFunction takes nothing returns nothing
    local unit u=GetEnumUnit()

    call TriggerRegisterUnitEvent(SDMStheTrigger(),u,EVENT_UNIT_DAMAGED)

    set u=null
endfunction
function theSDMSTriggerActions takes nothing returns nothing
    local trigger UnitEnter=CreateTrigger()
    local trigger TextTagCreate=SDMStheTrigger()

    call TriggerRegisterEnterRectSimple(UnitEnter,GetPlayableMapRect())
    call TriggerAddAction(UnitEnter,function SDMSTriggerRegisterUnitDamaged)
    call ForGroupBJ(GetUnitsInRectAll(GetPlayableMapRect()),function SDMSGroupFunction)

    set UnitEnter=null
    set TextTagCreate=null
endfunction
//========================================
//---------------Не трогать!--------------
//========================================
function InitTrig_the_SDM_Ttrigger takes nothing returns nothing
    local trigger tr=CreateTrigger()

    set udg_SDMStrigger=CreateTrigger()//Тут также меняется название глобальной переменной типа триггер.
    call TriggerAddAction(SDMStheTrigger(),function SDMSCreateTextTag)
    call TriggerRegisterTimerEventSingle(tr,0.0)
    call TriggerAddAction(tr,function theSDMSTriggerActions)

    set tr=null
endfunction
Карта прилагается

Принятый ответ

Эмм что за ерунда, сократил код, убрав всё лишнее, но утечки все равно остаются, по 1.5 - 2 хэндла за каждое нанесение урона (тип хэндла не знаю как посмотреть). Когда триггер отключаешь, то всё нормально.
Сокращенный код
function SDMSCreateTextTag takes nothing returns nothing
    local unit u=GetTriggerUnit()
    local unit s=GetEventDamageSource()
    local integer i=GetConvertedPlayerId(GetOwningPlayer(u))
    local texttag tt=CreateTextTag()
    local real dmg=GetEventDamage()

    if ( dmg > 1.00 ) and ( dmg < 9999.00 ) then
        if GetPlayerId(GetOwningPlayer(u))==12 then
            call SetTextTagText(tt, "|cff9db9eb-"+I2S(R2I(dmg))+"|r", 0.023)
        else
            call SetTextTagText(tt, "|cffffa500-"+I2S(R2I(dmg))+"|r", 0.023)
        endif
        call SetTextTagPosUnit(tt, u, 0)
        call SetTextTagColor(tt, 255, 255, 255, 255) 
        call SetTextTagVelocity(tt, 0.05325*Cos(90 * bj_DEGTORAD), 0.05325*Sin(90 * bj_DEGTORAD))
        call SetTextTagPermanent(tt, false)
        call SetTextTagLifespan(tt, 1.0)
        call SetTextTagFadepoint(tt, 0.0)
    endif
    call PolledWait(2.0)

    call DestroyTextTag(tt)
    set u=null
    set s=null
    set i=0
    set dmg=0
    set tt=null
endfunction

function SDMSTriggerRegisterUnitDamaged takes nothing returns nothing
    call TriggerRegisterUnitEvent(udg_SDMStrigger,GetEnteringUnit(),EVENT_UNIT_DAMAGED)
endfunction

function theSDMSTriggerActions takes nothing returns nothing
    local trigger UnitEnter=CreateTrigger()

    call TriggerRegisterEnterRectSimple(UnitEnter, gg_rct_Arena)
    call TriggerAddAction(UnitEnter,function SDMSTriggerRegisterUnitDamaged)

    set UnitEnter=null
endfunction

function InitTrig_the_SDMS_Trigger takes nothing returns nothing
    local trigger tr=CreateTrigger()

    set udg_SDMStrigger=CreateTrigger()//Тут также меняется название глобальной переменной типа триггер.
    call TriggerAddAction(udg_SDMStrigger,function SDMSCreateTextTag)
    call TriggerRegisterTimerEventSingle(tr,0.0)
    call TriggerAddAction(tr,function theSDMSTriggerActions)

    set tr=null
endfunction
Wait вызывает утечки ((
Пришлось делать через таймер
Этот комментарий удален
1
24
8 лет назад
1
Хах, знакомый триггер) Лет 100 назад натыкался на него. Это же чтобы цветной урон выводить при получении урона. Он не утечный, насколько я помню. Копировал это ещё когда про утечки не знал и удивлялся почему карта стала наоборот чуть меньше лагать.
Советую почитать про утечки как следует. Или внимательно просмотреть карту Leak вот здесь xgm.guru/p/wc3/bpe
0
15
8 лет назад
0
call PolledWait(lifeTime2)
set u=null
set s=null
set pl=null
set pl2=null
set l=null
set i=0
set fontSize=0
set lifeTime=0
set lifeTime2=0
set dmg=0
set minus=""
set plus=""
set textColor=""
call DestroyTextTag(tt)
set tt=null
Ага, не утечный.
0
24
8 лет назад
0
насколько я помню
Лет 100 назад
0
28
8 лет назад
0
хотелось бы увидеть данные счётчика хэндлов а именно количество утечек и их тип
0
9
8 лет назад
0
Эмм что за ерунда, сократил код, убрав всё лишнее, но утечки все равно остаются, по 1.5 - 2 хэндла за каждое нанесение урона (тип хэндла не знаю как посмотреть). Когда триггер отключаешь, то всё нормально.
Сокращенный код
function SDMSCreateTextTag takes nothing returns nothing
    local unit u=GetTriggerUnit()
    local unit s=GetEventDamageSource()
    local integer i=GetConvertedPlayerId(GetOwningPlayer(u))
    local texttag tt=CreateTextTag()
    local real dmg=GetEventDamage()

    if ( dmg > 1.00 ) and ( dmg < 9999.00 ) then
        if GetPlayerId(GetOwningPlayer(u))==12 then
            call SetTextTagText(tt, "|cff9db9eb-"+I2S(R2I(dmg))+"|r", 0.023)
        else
            call SetTextTagText(tt, "|cffffa500-"+I2S(R2I(dmg))+"|r", 0.023)
        endif
        call SetTextTagPosUnit(tt, u, 0)
        call SetTextTagColor(tt, 255, 255, 255, 255) 
        call SetTextTagVelocity(tt, 0.05325*Cos(90 * bj_DEGTORAD), 0.05325*Sin(90 * bj_DEGTORAD))
        call SetTextTagPermanent(tt, false)
        call SetTextTagLifespan(tt, 1.0)
        call SetTextTagFadepoint(tt, 0.0)
    endif
    call PolledWait(2.0)

    call DestroyTextTag(tt)
    set u=null
    set s=null
    set i=0
    set dmg=0
    set tt=null
endfunction

function SDMSTriggerRegisterUnitDamaged takes nothing returns nothing
    call TriggerRegisterUnitEvent(udg_SDMStrigger,GetEnteringUnit(),EVENT_UNIT_DAMAGED)
endfunction

function theSDMSTriggerActions takes nothing returns nothing
    local trigger UnitEnter=CreateTrigger()

    call TriggerRegisterEnterRectSimple(UnitEnter, gg_rct_Arena)
    call TriggerAddAction(UnitEnter,function SDMSTriggerRegisterUnitDamaged)

    set UnitEnter=null
endfunction

function InitTrig_the_SDMS_Trigger takes nothing returns nothing
    local trigger tr=CreateTrigger()

    set udg_SDMStrigger=CreateTrigger()//Тут также меняется название глобальной переменной типа триггер.
    call TriggerAddAction(udg_SDMStrigger,function SDMSCreateTextTag)
    call TriggerRegisterTimerEventSingle(tr,0.0)
    call TriggerAddAction(tr,function theSDMSTriggerActions)

    set tr=null
endfunction
Wait вызывает утечки ((
Пришлось делать через таймер
Принятый ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.