[JASS]一些TC與Event洩漏與占用H2I研究

各類的進階專題研究、WE Bug討論等。

版主: crassorz, tv580025

[JASS]一些TC與Event洩漏與占用H2I研究

文章Weberkkk » 2010年01月08日 5:03 pm


原理:利用HashTable容量無限的特性,把使用過的H2I位置做紀錄
   藉此觀察資源是否被釋出、重複使用

結論:有完整Remove與SetNull的空間都會被完整的回收
   不SetNull會有洩漏(有興趣的自己改代碼就知道)
   TC會跟隨Trigger被刪除
   TA不會跟隨Trigger被刪除

   一個Trigger塞入大量TC之後,只要刪除Trigger則所有TC一起被清除
   一個Trigger塞入大量Event之後,只要刪除Trigger則所有Event一起被清除
   根據Event隨Trigger自動消滅的特性,新型態的AUD非常好寫


   從方法A回收的TC數量1498、方法B的999、方法C的500
   與(MaxH2I減一開始創的Location的H2I)兩兩對照
   可以發現一件事情
   就是一個線程內申請的所有Handle即使被刪除,仍然會占用空間
   直到線程結束才會釋放

   釋放後的空間,無論原本的Handle類型如何,最後都有機會被其他類型Handle使用
   由測試可以很明顯的看出T、TA、TC三種Handle
   在經過幾次的清空、再創之後,TC使用過所有申請過的位置




//======================================================
//   TA與TC
//======================================================


function TestTA takes nothing returns nothing
endfunction
function TestTC takes nothing returns boolean
    return true
endfunction


//======================================================
//
//方法A:創T,加入TA與TC,刪除TA,刪除T
//結果A:無洩漏,MaxH2I-HashStart=1498~1502,總TC位置=1498
//
//======================================================

function TestTCCoreA takes nothing returns nothing
local trigger T
local triggeraction TA
local triggercondition TC
local integer A = 0
local integer I
local integer Count
local integer Use = 0
local integer Max = 0
local integer testN = 500

    loop
        exitwhen A >= testN
        set T = CreateTrigger()
        set TC = TriggerAddCondition(T,Condition(function TestTC))
        set TA = TriggerAddAction(T,function TestTA)
        set I = GetHandleId(TC)
        call TriggerRemoveAction(T,TA)
        call DestroyTrigger(T)
        set Count = LoadInteger(udg_HT,0,I) + 1
        call SaveInteger(udg_HT,0,I,Count)
        if Count > 1 then
            set Use = Use + 1
        else
            set udg_A = udg_A+1
        endif
        if I > Max then
            set Max = I
        endif
        set A = A+1
    endloop

    call BJDebugMsg("|c00ffcc22"+I2S(testN)+"|r個TC,有|c00ffcc22"+I2S(Use)+"|r個H2I重覆,MaxH2I=|c00ffcc22"+I2S(Max-udg_HashStart)+"|r,總TC位置=|c00ffcc22"+I2S(udg_A)+"|r")

    set T = null
    set TC = null
    set TA = null
endfunction

//======================================================
//
//方法B:創T,加入TC,刪除T
//結果B:無洩漏,MaxH2I-HashStart=998~1002,總TC位置=999
//
//======================================================

function TestTCCoreB takes nothing returns nothing
local trigger T
local triggeraction TA
local triggercondition TC
local integer A = 0
local integer I
local integer Count
local integer Use = 0
local integer Max = 0
local integer testN = 500

    loop
        exitwhen A >= testN
        set T = CreateTrigger()
        set TC = TriggerAddCondition(T,Condition(function TestTC))
        set I = GetHandleId(TC)
        call DestroyTrigger(T)
        set Count = LoadInteger(udg_HT,0,I) + 1
        call SaveInteger(udg_HT,0,I,Count)
        if Count > 1 then
            set Use = Use + 1
        else
            set udg_A = udg_A+1
        endif
        if I > Max then
            set Max = I
        endif
        set A = A+1
    endloop

    call BJDebugMsg("|c00ffcc22"+I2S(testN)+"|r個TC,有|c00ffcc22"+I2S(Use)+"|r個H2I重覆,MaxH2I=|c00ffcc22"+I2S(Max-udg_HashStart)+"|r,總TC位置=|c00ffcc22"+I2S(udg_A)+"|r")

    set T = null
    set TC = null
    set TA = null
endfunction

//======================================================
//
//方法C:創T,加入TCx500,刪除T
//結果C:無洩漏,MaxH2I-HashStart=502~503,總TC位置=501
//
//======================================================


function TestTCCoreC takes nothing returns nothing
local trigger T
local triggeraction TA
local triggercondition TC
local integer A = 0
local integer I
local integer Count
local integer Use = 0
local integer Max = 0
local integer testN = 500

    set T = CreateTrigger()
    loop
        exitwhen A >= testN
        set TC = TriggerAddCondition(T,Condition(function TestTC))
        set I = GetHandleId(TC)
        set Count = LoadInteger(udg_HT,0,I) + 1
        call SaveInteger(udg_HT,0,I,Count)
        if Count > 1 then
            set Use = Use + 1
        else
            set udg_A = udg_A+1
        endif
        if I > Max then
            set Max = I
        endif
        set A = A+1
    endloop
    call DestroyTrigger(T)

    call BJDebugMsg("|c00ffcc22"+I2S(testN)+"|r個TC,有|c00ffcc22"+I2S(Use)+"|r個H2I重覆,MaxH2I=|c00ffcc22"+I2S(Max-udg_HashStart)+"|r,總TC位置=|c00ffcc22"+I2S(udg_A)+"|r")

    set T = null
    set TC = null
    set TA = null
endfunction





//======================================================
//
//方法D:創T,加入Eventx500,刪除T
//結果D:無洩漏,MaxH2I-HashStart=502~503,總Event位置=501
//
//======================================================


function TestTCCoreD takes nothing returns nothing
local trigger T
local triggeraction TA
local event EV
local integer A = 0
local integer I
local integer Count
local integer Use = 0
local integer Max = 0
local integer testN = 500
local unit U = CreateUnit(Player(0),'hfoo',0,0,270)

    set T = CreateTrigger()
    loop
        exitwhen A >= testN
        set EV = TriggerRegisterUnitEvent(T,U,EVENT_UNIT_DAMAGED)
        set I = GetHandleId(EV)
        set Count = LoadInteger(udg_HT,0,I) + 1
        call SaveInteger(udg_HT,0,I,Count)
        if Count > 1 then
            set Use = Use + 1
        else
            set udg_A = udg_A+1
        endif
        if I > Max then
            set Max = I
        endif
        set A = A+1
    endloop
    call DestroyTrigger(T)
    call RemoveUnit(U)

    call BJDebugMsg("|c00ffcc22"+I2S(testN)+"|r個Event,有|c00ffcc22"+I2S(Use)+"|r個H2I重覆,MaxH2I=|c00ffcc22"+I2S(Max-udg_HashStart)+"|r,總Event位置=|c00ffcc22"+I2S(udg_A)+"|r")


    set U = null
    set T = null
    set EV = null
    set TA = null
endfunction





//===========================================================================
function InitTrig_TestTC takes nothing returns nothing
local location P = Location(0,0)
    set udg_HT = InitHashtable()
    set udg_HashStart = GetHandleId(P)
    call TimerStart(CreateTimer(),0.2,true,function TestTCCoreD )
    call RemoveLocation(P)
    set P = null
endfunction

回到頁頂

◆◆◆◆◆ 《 免費線上簽約服務,你也可以改變世界 》 ◆◆◆◆◆
 
「你知道打一場三國,會消耗多少能量嗎? 燃燒的能量,少於栽培的能量。」
「宇宙能量在不斷減少,所以WB發明了將玩家感情轉換為宇宙能量的技術。」
「主堡被推掉的瞬間,因戰敗爆發的各種情感,就是WB想蒐集的宇宙能量。」
「默契越好的玩家,釋放的能量越大,最厲害的團隊,會爆發出最強的能量。」
「XD化程度與能量蒐集率有關,WB理所當然的進行三國XD改造與實驗。」
「每次RE都會造成平行世界能量增幅,再過不久也許能培育出三國之神吧。」
頭像
Weberkkk
騎士
騎士
 
文章: 241
註冊時間: 2008年04月14日 12:06 am

Re: [JASS]一些TC與Event洩漏與占用H2I研究

文章crassorz » 2010年01月09日 10:05 am

越來越覺得JASS真是龜毛的程式碼= ="
圖檔
我決定不再對伸手牌起反應
除非很有趣
頭像
crassorz
死亡騎士
死亡騎士
 
文章: 2338
註冊時間: 2008年04月06日 5:40 pm
來自: 什麼都有的雜物間

Re: [JASS]一些TC與Event洩漏與占用H2I研究

文章tv580025 » 2010年02月13日 1:06 pm

Weberkkk 寫:結論:有完整Remove與SetNull的空間都會被完整的回收
   不SetNull會有洩漏(有興趣的自己改代碼就知道)
   TC會跟隨Trigger被刪除
   TA不會跟隨Trigger被刪除

這個觀點有誤...

當TC有用HASH函數與T存入同parentKey時

再使用HASH函數讀出並刪除該T後

同parentKey目錄下的TC才會連帶刪除

 
圖檔
http://weo.sabi.tw/blog <= 這是我的部落格
http://plurk.com/Neo_Yang <= 噗浪請按我


圖檔  凡事不經思索便行動 一條腸子直通到底的笨蛋
頭像
tv580025
冰霜翼龍
冰霜翼龍
 
文章: 1644
註冊時間: 2006年02月09日 12:29 pm
來自: Matrix

Re: [JASS]一些TC與Event洩漏與占用H2I研究

文章Weberkkk » 2010年02月14日 8:09 pm

本次測試與HT無關
我使用的都是HT的Integer讀寫,換成GC一樣能測試

set I = GetHandleId(TC)
set Count = LoadInteger(udg_HT,0,I) + 1
call SaveInteger(udg_HT,0,I,Count)


另外由本測試也可以發現Handle刪除並且確實SetNull之後
H2I的值會被回收再利用於其他Handle

==================================================

至於你提到的部分也許是HT的一些BUG或怎樣的
我就不清楚了
◆◆◆◆◆ 《 免費線上簽約服務,你也可以改變世界 》 ◆◆◆◆◆
 
「你知道打一場三國,會消耗多少能量嗎? 燃燒的能量,少於栽培的能量。」
「宇宙能量在不斷減少,所以WB發明了將玩家感情轉換為宇宙能量的技術。」
「主堡被推掉的瞬間,因戰敗爆發的各種情感,就是WB想蒐集的宇宙能量。」
「默契越好的玩家,釋放的能量越大,最厲害的團隊,會爆發出最強的能量。」
「XD化程度與能量蒐集率有關,WB理所當然的進行三國XD改造與實驗。」
「每次RE都會造成平行世界能量增幅,再過不久也許能培育出三國之神吧。」
頭像
Weberkkk
騎士
騎士
 
文章: 241
註冊時間: 2008年04月14日 12:06 am

Re: [JASS]一些TC與Event洩漏與占用H2I研究

文章tv580025 » 2010年02月14日 11:37 pm

Weberkkk 寫:本次測試與HT無關
我使用的都是HT的Integer讀寫,換成GC一樣能測試

set I = GetHandleId(TC)
set Count = LoadInteger(udg_HT,0,I) + 1
call SaveInteger(udg_HT,0,I,Count)


另外由本測試也可以發現Handle刪除並且確實SetNull之後
H2I的值會被回收再利用於其他Handle

TC自動清空算是不明的BUG

但是多半要滿足特定條件才會自動清空

像我上面所列出的就算是一種條件

要是不清的話Handle的值會一直膨脹

你只需要查看上面的附件便可明白

與其為了未知的BUG而不清空造成洩漏

倒不如多寫幾行清空的函數還比較實在
圖檔
http://weo.sabi.tw/blog <= 這是我的部落格
http://plurk.com/Neo_Yang <= 噗浪請按我


圖檔  凡事不經思索便行動 一條腸子直通到底的笨蛋
頭像
tv580025
冰霜翼龍
冰霜翼龍
 
文章: 1644
註冊時間: 2006年02月09日 12:29 pm
來自: Matrix

Re: [JASS]一些TC與Event洩漏與占用H2I研究

文章tv580025 » 2010年03月04日 2:21 am

function Unit_Damage_Condition takes nothing returns boolean
    return false
endfunction

function Unit_Death_Condition takes nothing returns nothing
    local unit              u = GetTriggerUnit()
    local trigger           t = LoadTriggerHandle(udg_H,GetHandleId(u),0)
    local triggercondition tc = LoadTriggerConditionHandle(udg_H,GetHandleId(u),1)
    call TriggerRemoveCondition(t,tc)
    call DestroyTrigger(t)
    call RemoveUnit(u)

    set u  = CreateUnit( Player(12),GetUnitTypeId(GetTriggerUnit()),0.00,0.00,0.00 )
    set t  = CreateTrigger()
    set tc = TriggerAddCondition( t,Condition(function Unit_Damage_Condition) )
    call TriggerRegisterUnitEvent(t,u,EVENT_UNIT_DAMAGED)
    call SaveTriggerHandle(udg_H,GetHandleId(u),0,t)
    //call SaveTriggerConditionHandle(udg_H,GetHandleId(u),1,tc)
    call DisplayTextToPlayer( Player(0),0,0,I2S(GetHandleId(t)) )

    set u  = null
    set t  = null
    set tc = null
endfunction

//===========================================================================
function InitTrig_Unit_Death takes nothing returns nothing
    set gg_trg_Unit_Death = CreateTrigger()
    call TriggerRegisterPlayerUnitEvent( gg_trg_Unit_Death,Player(12),EVENT_PLAYER_UNIT_DEATH,null )
    call TriggerAddCondition( gg_trg_Unit_Death,Condition( function Unit_Death_Condition ) )

    call FogModifierStart( CreateFogModifierRect(Player(0),FOG_OF_WAR_VISIBLE,bj_mapInitialPlayableArea,true,false) )
    set udg_H = InitHashtable()
endfunction

這是我之前附上的附件函數

只要測一下便知洩漏有沒有  

回到頁頂

圖檔
http://weo.sabi.tw/blog <= 這是我的部落格
http://plurk.com/Neo_Yang <= 噗浪請按我


圖檔  凡事不經思索便行動 一條腸子直通到底的笨蛋
頭像
tv580025
冰霜翼龍
冰霜翼龍
 
文章: 1644
註冊時間: 2006年02月09日 12:29 pm
來自: Matrix


回到 專題討論區

誰在線上

正在瀏覽這個版面的使用者:沒有註冊會員 和 1 位訪客