数组绑定系统
//======================================2009.2.24再次优化精简代码=======================//======================同时改为单链表,减少2个数组======================================
2009.2.23 再次精简代码 减少了近一半代码量
前几天 aeris 和 cccty1l 讨论了很久的 hash 写法
看了帖子```受益良多 链接: http://bbs.wow8.org/thread-87418-1-2.html http://bbs.wow8.org/thread-87523-1-1.html
于是我也写了个 数组绑定系统
欢迎大家指出不足
PS:我是用WE Helper编写的 (它也有vj功能,。我只利用那个可以定义全局变量) 所以如果要使用的话 请把globals里的全局变量 用 变量编辑器设置好``同时代码里变量也需要意义修改(似乎好麻烦的说```) WE Helper下载地址:http://www.islga.org/bbs/read.php?tid=7677&fpage=7
或者 下载 数组绑定系统b3(普通WE移植版).w3x
再ps:里面还有个缓存系统``我拿那个来对比效率的。。。感觉似乎差不多。。。(单位狂加。加到卡``)
似乎别人说的 hash写法 都是缓存的n倍。。```也许我算法效率太低?希望各位帮忙 提出改进建议```
代码说明:
SetDataInt 储存整数 SetDataReal 储存实数 SetDataString 储存字符串
例:call SetDataInt(整数A, 被绑定的handle类型数据B, 储存数据的名字c,要储存的整数d)
//A可以是任意数字(值被B覆盖);B,比如计时器,单位等;C要存的数据 名字叫什么;d 储存的数据。
//比如给单位udg_u 绑定数字174 名字叫"num" call SetDataInt(0,udg_u,"num",174)
// 实数 字符串的储存 获取 销毁 均以此类推
GetDataInt 储存整数 GetDataReal 储存实数 GetDataString 储存字符串
例:local integer i=GetDataInt(0,udg_u,"num")//取出前面存的那个174
DestroyDataInt 清除整数 DestroyDataReal 清除实数 DestroyDataString 清除字符串
例:call DestroyDataInt (0,udg_u,"num")//消除前面存的那个174
全部代码如下:
//======================================2009.2.24再次优化精简代码=======================
//======================同时改为单链表,减少2个数组======================================
globals
handle D_H
integer D_I
integer Length=0
integer Last=0
integer array Last_Last
integer array Data_H
integer array Data_h
integer array Data_Next
integer array Data_Int
real array Data_Real
stringarray Data_String
boolean array Data_H_Int
boolean array Data_H_Real
boolean array Data_H_String
endglobals
constant function S2HI takes string i returns integer
return i
return 0
endfunction
constant function HI2S takes integer i returns string
return i
return null
endfunction
function SetData takes integer D_I,integer D_S returns integer
local integer Li=(D_I+D_S)-(D_I+D_S)/8191*8191
local boolean b=FALSE
set D_I=D_I-D_S
set D_S=Data_H
if D_S!=0 then
loop
if Data_h==D_I then
return D_S
endif
exitwhen Data_Next==0
set D_S=Data_Next
endloop
set Li=D_S
set b=TRUE
endif
if Last!=0 then
set D_S=Last_Last
set Last_Last=0
set Last=Last-1
else
set D_S=Length+1
set Length=D_S
if Length>8191 then
return -174
endif
endif
if b then
set Data_Next=D_S
else
set Data_H=D_S
endif
set Data_h=D_I
return D_S
endfunction
function SetDataInt takes integer D_I,handle D_H,string Name,integer Data returns nothing
set D_I=SetData(D_I,S2HI(Name))
if D_I!=-174 then
set Data_Int=Data
set Data_H_Int=TRUE
endif
endfunction
function SetDataReal takes integer D_I,handle D_H,string Name,real Data returns nothing
set D_I=SetData(D_I,S2HI(Name))
if D_I!=-174 then
set Data_Real=Data
set Data_H_Real=TRUE
endif
endfunction
function SetDataString takes integer D_I,handle D_H,string Name,string Data returns nothing
set D_I=SetData(D_I,S2HI(Name))
if D_I!=-174 then
set Data_String=Data
set Data_H_String=TRUE
endif
endfunction
function GetData takes integer D_I,integer D_S returns integer
local integer Li=(D_I+D_S)-(D_I+D_S)/8191*8191
set D_I=D_I-D_S
set D_S=Data_H
if D_S==0 then
return -174
else
loop
if Data_h==D_I then
return D_S
endif
exitwhen Data_Next==0
set D_S=Data_Next
endloop
return -174
endif
endfunction
function GetDataInt takes integer D_I,handle D_H,string Name returns integer
set D_I=GetData(D_I,S2HI(Name))
if D_I!=-174 then
return Data_Int
else
return 0
endif
endfunction
function GetDataReal takes integer D_I,handle D_H,string Name returns real
set D_I=GetData(D_I,S2HI(Name))
if D_I!=-174 then
return Data_Real
else
return 0.
endif
endfunction
function GetDataString takes integer D_I,handle D_H,string Name returns string
set D_I=GetData(D_I,S2HI(Name))
if D_I!=-174 then
return Data_String
else
return null
endif
endfunction
function DestroyData takes integer D_I,integer D_S returns integer
local integer Li=(D_I+D_S)-(D_I+D_S)/8191*8191
local integer h=D_I-D_S
local integer I=Data_H
if I==0 then
return -174
else
loop
exitwhen Data_h==h
if Data_Next==0then
return -174
endif
set D_S=I
set I=Data_Next
endloop
if Data_H_Int==FALSE and Data_H_Real==FALSE and Data_H_String==FALSE then
set Last=Last+1
set Last_Last=I
set Data_h=0
set D_I=Data_Next
if Data_H==I then
if D_I!=0 then
set Data_H=D_I
else
set Data_H=0
endif
else
if D_I!=0 then
set Data_Next=D_I
else
set Data_Next=0
endif
endif
endif
return I
endif
endfunction
function DestroyDataInt takes integer D_I,handle D_H,string Name returns nothing
set D_I=DestroyData(D_I,S2HI(Name))
if D_I!=-174 then
set Data_H_Int=FALSE
endif
endfunction
function DestroyDataReal takes integer D_I,handle D_H,string Name returns nothing
set D_I=DestroyData(D_I,S2HI(Name))
if D_I!=-174 then
set Data_H_Real=FALSE
endif
endfunction
function DestroyDataString takes integer D_I,handle D_H,string Name returns nothing
set D_I=DestroyData(D_I,S2HI(Name))
if D_I!=-174 then
set Data_H_String=FALSE
endif
endfunction
///////////////////////////////////////////////////////////////////////////////// 很好很强大啊 橙子很辛苦 if I!=0 then
loop
if Data_h==D_I and Data_s==D_S then
if Data_H_Real==FALSE then
set Data_H_Real=TRUE
endif
set Data_Real=Data
return
endif
exitwhen Data_Next==0
set I=Data_Next
endloop
set Li=I
set b=TRUE
endif
这个一定会死掉的。。。。。 没死掉过呢`````
我去测试下..要链多少个才会死掉``
http://bbs.wow8.org/viewthread.php?tid=88337&page=1&fromuid=101045#pid1186283
这里 aeris 帮我做了个性能测试
我做了一个性能测试,比较缓存和LZ写的Hash法的性能差异
测试1
对2200个location进行数据绑定操作,代码如下:
function Trig_TimedTest_Actions takes nothing returns nothing
local integer i
local location loc
local integer watch
local real time
set watch = StopWatchCreate()
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
call cache.attachInteger(loc, "TEST", i)
set i = i + 1
endloop
set time = StopWatchMark(watch)
call StopWatchDestroy(watch)
call BJDebugMsg("缓存绑定: " + R2SW(time, 5, 5))
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
call cache.clean(loc)
set i = i + 1
endloop
call TriggerSleepAction(2.0)
set watch = StopWatchCreate()
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
call SetDataInt(0, loc, "TEST", i)
set i = i + 1
endloop
set time = StopWatchMark(watch)
call StopWatchDestroy(watch)
call BJDebugMsg("哈希绑定: " + R2SW(time, 5, 5))
call TriggerSleepAction(0.0)
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
call DestroyDataInt(0, loc, "TEST")
set i = i + 1
endloop
set loc = null
endfunction
这是某次的测试结果:
http://bbs.wow8.org/attachments/day_090221/20090221_fe763144da4cf6f2b59eOpzF20VFyDLS.png
对2200个location进行绑定操作,缓存用时大约0.09秒(平均),而Hash法用时0.025秒(平均)
测试2
在测试1的数据基础上,测试分别读取2200个绑定的数据,另外测试了空循环用时,以供对照
代码如下:
function Trig_TimedTest_Actions takes nothing returns nothing
local integer i
local location loc
local integer j
local integer watch
local real time
// 准备数据
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
call cache.attachInteger(loc, "TEST", i)
set i = i + 1
endloop
call TriggerSleepAction(0.0)
set watch = StopWatchCreate()
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
set j = cache.extractInteger(loc, "TEST")
set i = i + 1
endloop
set time = StopWatchMark(watch)
call StopWatchDestroy(watch)
call BJDebugMsg("缓存读取: " + R2SW(time, 5, 5))
call TriggerSleepAction(0.0)
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
call cache.clean(loc)
set i = i + 1
endloop
call TriggerSleepAction(2.0)
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
call SetDataInt(0, loc, "TEST", i)
set i = i + 1
endloop
call TriggerSleepAction(0.0)
set watch = StopWatchCreate()
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
set j = GetDataInt(0, loc, "TEST")
set i = i + 1
endloop
set time = StopWatchMark(watch)
call StopWatchDestroy(watch)
call BJDebugMsg("哈希读取: " + R2SW(time, 5, 5))
call TriggerSleepAction(0.0)
set watch = StopWatchCreate()
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
set i = i + 1
endloop
set time = StopWatchMark(watch)
call StopWatchDestroy(watch)
call BJDebugMsg("*对照* 空循环:" + R2SW(time, 5, 5))
call TriggerSleepAction(0.0)
set i = 0
loop
exitwhen (i >= testLocArray.size)
set loc = testLocArray<i>
call DestroyDataInt(0, loc, "TEST")
set i = i + 1
endloop
set loc = null
endfunction
测试结果如下:
http://bbs.wow8.org/attachments/day_090221/20090221_201c15a23530ba685204HRQ4RqOGO6VR.png
缓存读取大约0.023秒,哈希读取大约0.018秒,空循环本身耗时0.002秒
读取时,性能提高不大 测试过了.
完全不会死掉的...
globals
integer I=0
endglobals
function Trig____________________003_Actions takes nothing returns nothing
local integer D_I=174
local integer D_S=741
local integer Data=471
call DisplayTextToPlayer( Player(0), 0, 0, "上次循环了 "+I2S(I) +" 次")
set I=0
loop
if Data_h==D_I and Data_s==D_S then
if Data_H_Real==FALSE then
set Data_H_Real=TRUE
endif
set Data_Real=Data
return
endif
exitwhen Data_Next==0
set I=Data_Next
endloop
endfunction
//===========================================================================
function InitTrig____________________003 takes nothing returns nothing
local integer i=0
loop
exitwhen i>8191
set Data_Next=i+1
set i=i+1
endloop
set gg_trg____________________003 = CreateTrigger()
call TriggerRegisterPlayerEventEndCinematic( gg_trg____________________003, Player(0) )
call TriggerAddAction( gg_trg____________________003, function Trig____________________003_Actions )
endfunction
结果显示 第1次0
第2-3-4-5-....n次都是8192
而我的每1个链 都不可能会那么长的。。
而且``1个地图里 再怎么能存 ``最多也都存不到几千个数据的。。
2009.2.23 再次精简代码 减少了近一半代码量 使用缓存做0.02秒移动单位的函数没有这个的效率高么? aeris 测试的是 存入 和 读取 的效率对比
按他的测试结果
这个存 比缓存高3-4倍
取 只高一点点 实际上你没有考虑全局变量和本地变量的区别。全局变量在跨度比较大的时候读起来会不定期变慢 全局变量在跨度比较大的时候读起来会不定期变慢
这点..不太理解..
有相关资料 给我看看么? 增加个 数组绑定系统b3(普通WE移植版) 很简单地,你对一个全局变量赋值1w次,和对1w个全局变量每个一次赋值,速度差N倍,然后如果你在一个触发里面对100w个以上的全局变量赋值,会直接被喀嚓掉,而对一个全局变量赋值100w次是没问题的。 我怎么想到了page fault………………
对同一个变量赋值因为地址不变,不会产生page fault,对不同变量赋值,地址是变化的,总会产生page fault,极大地影响了执行速度………………
遁 按汇编来说.
对 同1个变量赋值时 寄存器 只要存1次变量地址
然后在寄存器 存个数据 之后移动数据进地址
而对不同变量 那需要每次多出 寄存器存变量地址的步骤?``
那.`````....我改单链表好了.....稍微省点操作````````其他的也就这样了..反正经测试 ``实际效果比缓存快 缓存的问题不在速度,主要是会出现诡异问题 诡异问题?
万望LS披露一下~~~ 字符串那些``
~~不过据测试这个确实是快了那么点.... 你去重复生成字符串然后往缓存里面扔,大概仍4k个字符串缓存就挂了,而且字符串存进去,flushStoredXX删不掉 那么继续减少运算量``改单链 少存个字符串句柄`` 这是为什么呢?~ 为什么呢 什么为什么呢 为什么什么呢
页:
[1]
2