[System] Timed Loop R32 Version Optimization!

  • Thread starter Thread starter dh-g
  • Ngày gửi Ngày gửi

dh-g

Fire in the hole!
Lão Làng GVN
Tham gia ngày
29/8/09
Bài viết
2,654
Reaction score
5,688
RepeatData 32

Standard version
PHP:
library R32 //version 1.11 by Daric,dhguardianes,19101994 
//*************************************************************************************************** 
//*             ____                       _   ____        _          _________   
//*            |  _ \ ___ _ __   ___  __ _| |_|  _ \  __ _| |_ __ _  |___ /___ \  
//*            | |_) / _ \ '_ \ / _ \/ _` | __| | | |/ _` | __/ _` |   |_ \ __) | 
//*            |  _ <  __/ |_) |  __/ (_| | |_| |_| | (_| | || (_| |  ___) / __/  
//*            |_| \_\___| .__/ \___|\__,_|\__|____/ \__,_|\__\__,_| |____/_____| 
//*                      |_|  
//* This system similar to T32 but has been improve  it's easy and convenient to use 
//*  
//*  R32_Tick is count number of iterations in cycle. 
//*  - Easy to use 
//*  - MUI for spell 
//*  - Store data by Struct 
//* How to uses? 
//* 
//*  private struct mystruct extends RepeatData 
//*      string myname 
//* 
//*      method onEnd takes nothing returns nothing 
//*          set this.myname = null 
//*          call BJDebugMsg("release") 
//*      endmethod 
//*  
//*      method onLoop takes nothing returns nothing 
//*          if R32_Tick == 96 then // (3 / R32_Period) = 96 R32_Tick 
//*              call this.stop() 
//*          else 
//*              call BJDebugMsg(this.myname) 
//*          endif 
//*      endmethod 
//*  endstruct 
//*  function test takes string name returns nothing 
//*      local mystruct this = mystruct.create(R32_Period, 0) 
//*      set this.myname = name 
//*  endfunction 
//*************************************************************************************************** 
    globals
        private constant    boolean     SafeMode    = false //False: Is Faster and Memory occupied!!! 
        //not fix below                                     //True:  Is Fast Memory optimize 
        private             timer       rT          = CreateTimer()
        public  constant    real        Period      = .031250000
        private             integer     tT          = 0
        public              integer     Tick        = 0 //very useful.
    endglobals
//*************************************************************************************************** 
private module locate 
    private method remove takes nothing returns nothing
        if this.prev==0 then
            set .head=this.next
        endif
        set this.next.prev=this.prev
        if this.next==0 then
            set .tail=this.prev
        endif
        set this.prev.next=this.next
    endmethod
         
    static if SafeMode then //Dynamic Indexing
        private static integer ins = 0 
        private static integer array insAR 
        static method alloc takes nothing returns thistype 
            local thistype this = insAR[0] 
            if this==0 then 
                set ins = ins + 1 
                set this = ins 
            else 
                set insAR[0] = insAR[this] 
            endif 
            return this 
        endmethod 
        method dealloc takes nothing returns thistype
            call this.remove() 
            set insAR[this] = insAR[0] 
            set insAR[0] = this 
            return this.next
        endmethod 
    else //Stack Array
        private static thistype array recycled
        private static integer recycledMax = 0
        private static integer lastAlloc = 0
        static method alloc takes nothing returns thistype
            if .recycledMax==0 then
                set .lastAlloc = .lastAlloc + 1
                return .lastAlloc
            endif
            set .recycledMax = .recycledMax - 1
            return .recycled[.recycledMax]
        endmethod
        method dealloc takes nothing returns thistype
            call this.remove()
            set .recycled[.recycledMax] = this
            set .recycledMax = .recycledMax + 1
            return this.next
        endmethod
    endif 
endmodule 
//*************************************************************************************************** 
private interface RepeatFace 
    method onLoop  takes nothing returns nothing defaults nothing 
    method onEnd   takes nothing returns nothing defaults nothing 
endinterface 
//*************************************************************************************************** 
struct RepeatData extends RepeatFace
    public integer rpt
    public integer rL
    public integer rtik
    public integer mrpt
    private thistype next
    private thistype prev
    
    implement locate
    
    private static thistype head=0
    private static thistype tail=0
    static method create takes real Loop, real maxLoop returns thistype
        local thistype this = thistype.alloc()
        
        if .tail==0 then
            set .tail=this
        endif
        
        if .head==0 then
            call TimerStart(rT,R32_Period,true,function thistype.rpLoop)
        endif
        
            set this.next=.head
            set this.prev=0
            if .head!=0 then
                set .head.prev=this
            endif
            set .head=this
            
            if Loop==0 then
                set this.mrpt=0
                set this.rL=1
            else
                if Loop<R32_Period then
                    set this.rL=1
                else
                    set this.rL=R2I(Loop/R32_Period)
                endif
                if maxLoop==0 then
                    set this.mrpt=999999
                else
                    set this.mrpt=R2I(maxLoop/Loop)
                endif
            endif
            set this.rpt=0
            set this.rtik=this.rL + tT
            
        return this
    endmethod
    
    method stop takes nothing returns nothing
        set this.mrpt=0
        //call BJDebugMsg("R32 Release: "+I2S(this)) 
    endmethod
    
    private static method rpLoop takes nothing returns nothing
        local thistype this=.head
        set tT=tT+1
        loop
            exitwhen this==0
            if this.rtik<=tT then
                set this.rpt=this.rpt+1
                set R32_Tick=this.rpt
                //debug call BJDebugMsg("R32 S: "+I2S(this)+ " T: "+I2S(R32_Tick))
                call this.onLoop()
                if this.mrpt<=this.rpt then
                    call this.onEnd()
                    set this=this.dealloc()
                else
                    set this.rtik=this.rL + tT
                    set this=this.next
                endif
            else
                set this=this.next
            endif
        endloop
        if .head==0 then
            set tT=0
            call PauseTimer(rT)
        endif
    endmethod
endstruct
endlibrary

Super version
PHP:
library R32s //version 1.0 by Daric,dhguardianes,19101994 
//*************************************************************************************************** 
//*             ____                       _   ____        _          _________   
//*            |  _ \ ___ _ __   ___  __ _| |_|  _ \  __ _| |_ __ _  |___ /___ \  
//*            | |_) / _ \ '_ \ / _ \/ _` | __| | | |/ _` | __/ _` |   |_ \ __) | 
//*            |  _ <  __/ |_) |  __/ (_| | |_| |_| | (_| | || (_| |  ___) / __/  
//*            |_| \_\___| .__/ \___|\__,_|\__|____/ \__,_|\__\__,_| |____/_____| 
//*                      |_|  
//* This system similar to T32 but has been improve  it's easy and convenient to use 
//*  
//*  - Easy to use 
//*  - MUI for spell 
//*  - Store data by Struct 
//* How to uses? 
//* 
//*  private struct mystruct extends RepeatData 
//*      string myname 
//* 
//*      method onEnd takes nothing returns nothing 
//*          set this.myname = null 
//*          call BJDebugMsg("release") 
//*      endmethod 
//*  
//*      method onLoop takes integer R32_Tick returns nothing 
//*          if R32_Tick == 96 then // (3 / R32_Period) = 96 R32_Tick 
//*              call this.stop() 
//*          else 
//*              call BJDebugMsg(this.myname) 
//*          endif 
//*      endmethod 
//*  endstruct 
//*  function test takes string name returns nothing 
//*      local mystruct this = mystruct.create(R32_Period, 0) 
//*      set this.myname = name 
//*  endfunction 
//*************************************************************************************************** 
    globals
        //not fix below
        private             trigger                 rT          = CreateTrigger()
        private             integer                 used        = 0
        public  constant    real                    Period      = .031250000
        private             integer                 tT          = 0
        private             integer     array       ARRAY       [409550]
    endglobals
//*************************************************************************************************** 
private module locate 
    //Stack Array
    private static thistype array recycled
    private static integer recycledMax = 0
    private static integer lastAlloc = 0
    static method alloc takes nothing returns thistype
        if .recycledMax==0 then
            set .lastAlloc = .lastAlloc + 1
            return .lastAlloc
        endif
        set .recycledMax = .recycledMax - 1
        return .recycled[.recycledMax]
    endmethod
    method dealloc takes nothing returns thistype
        set .recycled[.recycledMax] = this
        set .recycledMax = .recycledMax + 1
        set used=used-1
        return this.next
    endmethod
endmodule 
//*************************************************************************************************** 
private interface RepeatFace 
    method onLoop  takes integer tick returns nothing defaults nothing 
    method onEnd   takes nothing      returns nothing defaults nothing 
endinterface 
//*************************************************************************************************** 
struct RepeatData extends RepeatFace
    public integer rpt
    public integer mrpt
    public integer rL
    
    //add/remove R32 to tick in tT (total tick)
    private thistype next
    private static thistype nex
    method SetR32 takes integer tik returns thistype
        set .nex=this.next
        if ARRAY[tik]==0 then
            set this.next=0
        else
            set this.next=ARRAY[tik]
        endif
        set ARRAY[tik]=this
        return .nex
    endmethod
    
    implement locate
    
    method stop takes nothing returns nothing
        set this.mrpt=0
        //call BJDebugMsg("R32 Release: "+I2S(this)) 
    endmethod
    
    private static thistype run
    private static method rpLoop takes nothing returns boolean
        set tT=tT+1
        set .run=ARRAY[tT]
        set ARRAY[tT]=0
        loop
            exitwhen .run==0
            set .run.rpt=.run.rpt+1
            //debug call BJDebugMsg("R32 S: "+I2S(this)+ " T: "+I2S(this.rpt))
            call .run.onLoop(.run.rpt)
            if .run.rpt>=.run.mrpt then
                call .run.onEnd()
                set .run=.run.dealloc()
            else
                set .run=.run.SetR32(.run.rL + tT)
            endif
        endloop
        return used==0
    endmethod
    
    private static method rpEnd takes nothing returns nothing
        set tT=0
        call TriggerClearConditions(rT)
        call TriggerClearActions(rT)
    endmethod
    
    private static thistype cre
    static method create takes real Loop, real maxLoop returns thistype
        set .cre = thistype.alloc()
        
        if used==0 then
            call TriggerAddCondition(rT,function thistype.rpLoop)
            call TriggerAddAction(rT,function thistype.rpEnd)
        endif
        set used=used+1
        
            if Loop==0 then
                set .cre.mrpt=0
                set .cre.rL=1
            else
                if Loop<R32_Period then
                    set .cre.rL=1
                else
                    set .cre.rL=R2I(Loop/R32_Period)
                endif
                if maxLoop==0 then
                    set .cre.mrpt=999999
                else
                    set .cre.mrpt=R2I(maxLoop/Loop)
                endif
            endif
            set .cre.rpt=0
            set .cre.next=0
            call .cre.SetR32(.cre.rL + tT)
            
        return .cre
    endmethod
    
    private static method onInit takes nothing returns nothing
        call TriggerRegisterTimerEvent(rT,.031250000,true)
    endmethod
endstruct
endlibrary

R32s
thuộc system Timed Loop sử dụng cơ chế và cách thức nhanh nhất War3, nhưng sẽ bù lại nhược điểm. sẽ hoạt động tốt trong vòng 4h và ngốn ram nhiều.(không đáng kể) thích hợp sử dụng map minigame nhanh win và xài nhiều timer

bản R32s đã thay đổi API của OnLoop
method onLoop takes integer tick returns nothing defaults nothing
lấy tick từ tick thay vì R32_Tick

Giới thiệu

đây là một phiên bản đại trùng tu của RepeatData32, theo suy luận của nhiều người phản ánh về system RepeatData32 khi sử dụng càng nhiều timer trong 1 lúc thì sẽ gây ra tình trạng tụt FPS khá cao. đó là do cơ chế hoạt động của RepeatData32. khi destroy 1 data, system không thể biết được data đó nằm vị trí index bao nhiêu trong mảng Array đó. Nên mỗi lần thế phải dùng vòng lặp loop qua hết mảng array xem là data nào. Mà số vòng loop thì phụ thuộc vào lượng Data trong mảng, càng nhiều Data thì sẽ càng làm trì trệ. Vì vậy RepeatData32 phải kiêm luôn mỗi lần loop phải kiểm tra luôn xem có thể destroy được chưa. nếu so với T32 thì khác. do dùng cơ chế List nên 1 Data của nó sẽ có 2 phần tử mắc xích (gắn với Data trước nó và sau nó), vì vậy khi destroy mình chẳng cần quan tâm nó ở vị trí nào trong List cả, cứ lấy Data trước nối lại với Data sau nó là xong. Vì vậy coder tùy ý thích destroy lúc nào cũng được.

do vậy phiên bản R32 này sẽ cải tiến dòng lặp theo cơ chế list. nhưng sẽ không chắc rằng system này so với T32 là ngang nhau hoặc chậm hơn. vì cải tiến thêm về allocate. nên sẽ nhanh hơn so với T32 nếu trong SafeMode chọn false!

Nhược điểm
sẽ chậm hơn 5% so với T32 nếu SafeMode chọn true
chậm hơn CTL

Ưu điểm
tốc độ xử lý nhanh hơn!
đơn giản sử dụng
tích hợp sẵn chức năng của Timed Loop và Repeat Loop.

Changelog
ver 1.11
tối ưu hóa code!
ver 1.10
loại bỏ OnStart vì tối ưu tốc độ đến mức có thể!
tối ưu hóa code theo suy luận 23250702

ver 1.09
loại bỏ TestMode
tối ưu hóa method Onstart!
ver 1.08
thay đổi cách thức hoạt động
"RepeatData" trong library sẽ được đổi tên thành R32
var R32_PERIOD sẽ đổi thành R32_Period



Trình hàm
¯¯¯¯¯¯¯¯
local mystruct this = mystruct.create(A,B)

A là thời gian của chu kì. cho phép tối thiểu 0.03125s, nếu var A set dưới quá con số cho phép thì thời gian chu kì ảnh hưởng cũng sẽ là 1/32

B là điểm đến. tức là thời gian giới hạn cho A
ví dụ:
A = 0.03125
B = 3,125
thì thời gian chạy chu kì sẽ là 10 lần!

nếu A hữu số. còn B là vô số thì thời gian chạy chu kì sẽ loop liên tiếp đến khi gọi this.stop()

nếu A là vô số còn B là hữu số thì thời gian chạy chỉ một lần

//đây sẽ chạy các code trong lúc chu kì chạy!
method onLoop takes nothing returns nothing
endmethod

//đây là chạy sau cùng khi gọi call this.stop()
method onEnd takes nothing returns nothing
endmethod



khi SafeMode set = true

tốc độ truy xuất sẽ chậm hơn và ít chiếm bộ nhớ hơn!

nếu = false
tốc độ truy xuất sẽ rất nhanh và chiếm RAM




test demo
[SPOIL]
Mã:
scope test initializer int
    private struct mystruct extends RepeatData
        string myname
        method onEnd takes nothing returns nothing
            set this.myname = null
            call BJDebugMsg("over 3s")
        endmethod
        method onLoop takes nothing returns nothing
            if R32_Tick == 96 then // (3 / R32_Period) = 96 R32_Tick
                call this.stop()
            else
                call BJDebugMsg(this.myname)
            endif
        endmethod

    endstruct
    function int takes nothing returns nothing
        local mystruct this = mystruct.create(R32_Period, 0)
        set this.myname = "haha"
    endfunction
endscope
[/SPOIL]

và gửi lời cảm ơn tới!
19101994,KuKulKan

P/S: mình cần những người như các bạn vì thế sẽ giúp R32 này thịnh hành tại box WE nhà mình >:D<, và đây cũng là TimedLoop do box WE mình phát triển :-?
 
Chỉnh sửa cuối:
ta vẫn chưa fix xong mà mi đã quăng lên rùi...
p/s: mi bảo ra xóa bài bên kia nhưng ta nào có biết xóa :2onion58: đó giờ post 4rum dc mấy lần đâu mà rành mí cái này :4onion30:
 
đính chính lại là true hay SafeMode của mi false đều chiếm RAM =))
 
đính chính lại là true hay SafeMode của mi false đều chiếm RAM =))

đúng cả 2 đều chiếm RAM :-j mà nếu true thì chiếm ít hơn false =)) và false sẽ nhanh hơn :-" true
 
system này đk a ưu ái quá nhỉ :6cool_smile:
 
CÓ THỂ sẽ còn up ver nữa và đó là ver cuối (tốn nh` chất xám cho nó quá rồi)
mà công nhận 2 thằng cũng rỗi thật lấy cái idea fix tới fix lui thành ra thế này...

dh-gà fix cái nhược lại lun nhá, nhược của nó sau khi up 1.09 thì dù chọn SafeMode cũng thua T32 ~5-10% thui
 
Like !!!

set this.rtik=R2I(this.rL/R32_Period) + tT nếu this.rL/R32_Period là 1 hằng số không đổi thì nên tính toán lúc đầu và cho sẵn vào 1 biến thì sẽ tiết kiêm được 1 tí chi phí xử lí, đừng hành hạ con CPU quá ^^

Và làm sao để truyền tham số như target caster..ect khi dùng R32 khi khởi tạo 1 struct nhỉ ( Ex: A a = A.create(target,caster) ) vì đa số người viết code họ thích gán ngay khi khởi tao struct (cho nó đep ý mà ^^) trừ khi tham số quá nhiều. Nếu hok đươc thì 1 điểm trừ :-"

Cho Kan hỏi tí..hơi tò mò, những con số so sánh 5% 10% 20% từ đâu mà ra nhỉ...các ban so sánh như thế nào để cho ra những con số ấy nhỉ :D
 
cái đó do dh-gà đo fps của R32 với T32 và CTL rùi so sánh theo % thui hỏi thêm hắn để biết thêm chi tiết nhé kan

còn cái vụ truyền tham số thì bó tay kan à, nhưng mình thấy cũng thế nếu phải set khi create = tham số truyền vào hay set khi onStart từ R32 thì cũng phải viết set nên có truyền hay không cũng thế thui ^^ chịu khó viết set đi đừng có -1 điểm oan thế

cái vụ this.rL/R32_Period mình đã fix ở ver sắp ra, thanks!
 
à cái vụ create mình hiểu ý kan mún nói rùi...

thay tên hàm create = tên khác và create = hàm đó, trong hàm create ( A.NAME(...) ) đó gọi cái hàm create để lặp ( A.create(Loop,maxLoop )

p/s đúng ý không nhỉ ???
 
cái này dùng trong trường hợp nào :5cool_ops:
 
để lặp các struct, kéo data theo thời gian để làm 1 việc gì đó mà mính mún (nói chung chung)

p/s 1.09 có lỗi nặng các bác tạm thời khoan xài nhá, mình đang fix và đợi tên dh-gà về test rùi sẽ cho ver mới nhất lên vào 1-2 ngày sau!
 
cái đó do dh-gà đo fps của R32 với T32 và CTL rùi so sánh theo % thui hỏi thêm hắn để biết thêm chi tiết nhé kan

còn cái vụ truyền tham số thì bó tay kan à, nhưng mình thấy cũng thế nếu phải set khi create = tham số truyền vào hay set khi onStart từ R32 thì cũng phải viết set nên có truyền hay không cũng thế thui ^^ chịu khó viết set đi đừng có -1 điểm oan thế

cái vụ this.rL/R32_Period mình đã fix ở ver sắp ra, thanks!

cách là tạo 1 số timer nhất định đi so sánh tốc độ với nhau ví dụ ước tính dc nó sẽ ảnh hưởng từ giao động 50~53 mình thì bắt số FPS yếu nhất có thể giao động tới. ở đây là 50 của T32 còn R32 ví dụ dc giao động 52~55 mình lấy 52 của R32

và sẽ cho ra

(FPS càng cao thì đại biểu system càng nhanh)

R32 được 52 FPS
T32 được 50 FPS

lấy con số 64 - số FPS đó tương ứng sẽ ra kết quả (vì 64 là FPS tiêu chuẩn mượt nhất có thể show trong war3 :-"
ex
64-50 = 14
64-52 = 12

14 sẽ là 85.8% của 12
12 sẽ là 14.2% của 14

vậy là kết quả sẽ là T32 sẽ chậm hơn 14%


P/S: nhiều người hỏi tại sao họ không thể test được cái giao động FPS tụt đến tầm 5x. lý do có thể là do cấu hình máy mạnh. vì test vụ này tớ đã sử dụng 1 chiếc đời cũ để test :-?
cái này dùng trong trường hợp nào :5cool_ops:

nó là dành cho tất cả trường hợp của war3 làm spell hay system :|
 
Chỉnh sửa cuối:
ver 1.10
loại bỏ OnStart vì tối ưu tốc độ đến mức có thể!
tối ưu hóa code theo suy luận 23250702
ver 1.10 đã ra đời rùi >:D<
chắc vài bửa nữa sẽ thêm R32x tốc độ nhanh nhất của Timed Loop war3. nhưng sẽ bù lại số RAM ăn khủng :| cho ai thềm tốc độ =))

xin cảm ơn kan đã với suy luận đó :D

P/S: R32x đã có hàng. trong giai đoạn Alpha. và được ước tính rằng. nó sẽ ăn 30m RAM trong vòng 4 tiếng đồng hồ. đó là cái giá phải trả cho super speed :-" nó sẽ nhanh hơn T32 25% với CTL 23% R32 20% trong bản safe true (bản safe false thì nhanh hơn tý :-")
 
Chỉnh sửa cuối:
ta thấy mi bỏ nghề đầu bếp làm quản cáo tiếp thị dc đấy :4cool_baffle:
 
2 a có thử thẩy lên hive chưa, bn nn bên ýk công bằng lắm
cơ màk có lần post tên mod chửi em là "Chúng tôi đã có nhiều Time system khác rồi nên cái này chúng tôi không cần nữa", câu nói làm như system đáng vứt đi lắm ấy :9cool_too_sad:

a hùng tiếp thị giỏi thì qua bển típ dùm yk :6cool_smile:
 
:1cool_look_down: thử liền dh-gà quăng R32 qua hive với mí web khác lun, chứ chỉ quảng cáo trong đây thì cũng hok có bao nhiu ng` biết và xài cả

p/s ghi lại cái credit à, không thôi ta giết mi :6cool_beat_brick:
 
:1cool_look_down: thử liền dh-gà quăng R32 qua hive với mí web khác lun, chứ chỉ quảng cáo trong đây thì cũng hok có bao nhiu ng` biết và xài cả

p/s ghi lại cái credit à, không thôi ta giết mi :6cool_beat_brick:

thử quăng lên thì họ chỉ pháng 1 câu "Chúng tôi đã có nhiều Time system khác rồi nên cái này chúng tôi không cần nữa" :|
 
ta thấy mi bỏ nghề đầu bếp làm quản cáo tiếp thị dc đấy :4cool_baffle:

làm bếp đã hơn tiếp thị :-"

2 a có thử thẩy lên hive chưa, bn nn bên ýk công bằng lắm
cơ màk có lần post tên mod chửi em là "Chúng tôi đã có nhiều Time system khác rồi nên cái này chúng tôi không cần nữa", câu nói làm như system đáng vứt đi lắm ấy :9cool_too_sad:

a hùng tiếp thị giỏi thì qua bển típ dùm yk :6cool_smile:

khi nào a ở bên e thì a sẽ qua bên em :1cool_byebye:


đã ra lò R32s system TimedLoop nhanh nhất war3 \m/
 
sao mi trả lời giống tên Daric thế :| không quăng lên thì làm sao quảng cáo đây :-w
 
Back
Top