HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Viable handle var system?

10-04-2007, 02:08 AM#1
Blackroot
*Upated
This is a very simple handle var system I made, mainly to pass across structs. I wanted to avoid strings / leaks completely, and I tried to make it as fast as possible. But I'm wondering if this is actually going to be faster then other systems? If the array is decently large, would it take longer then conventional systems?

Collapse JASS:
function H2I takes handle h returns integer
 return h
 return 0
endfunction

globals
 integer array Attach_Array_AH
 integer array Attach_Array_AN
 integer array Attach_Array_Val
 integer Attach_ArrayN = 0
endglobals

function Attach takes handle AH, integer number, integer val returns nothing
 set Attach_Array_AH[Attach_ArrayN] = H2I(AH)
 set Attach_Array_AN[Attach_ArrayN] = number
 set Attach_Array_Val[Attach_ArrayN] = val
 set Attach_ArrayN = Attach_ArrayN + 1
endfunction

function Retreive takes handle AH, integer number returns integer
 local integer I = Attach_ArrayN
 local integer HV = H2I(AH)

 loop
  if(Attach_Array_AH[i] == HV) and (Attach_Array_AN[i] == number)then
   return Attach_Array_Val[i]
  endif
  exitwhen(I == 0)
  set I = I - 1
 endloop
 return 0
endfunction

function FlushAttached takes handle AH, integer number returns integer
 local integer I = Attach_ArrayN
 local integer HV = H2I(AH)

 loop 
  if(Attach_Array_AH[i] == HV) and (Attach_Array_AN[i] == number)then
   loop
    exitwhen(I == Attach_ArrayN)
    set Attach_Array_AH[I-1] = Attach_Array_AH[i]
    set Attach_Array_AN[I-1] = Attach_Array_AN[i]
    set Attach_Array_Val[I-1] = Attach_Array_Val[i]
    set I = I + 1 
   endloop
   set Attach_ArrayN = Attach_ArrayN - 1
   return 1
  endif
  set I = I - 1
 endloop
 return 0
endfunction

It's pritty simple. Here's an example:
Collapse JASS:
function Test2 takes nothing returns nothing
 local timer T = GetExpiredTimer()
 local integer I = Retreive(T, 1)
 local integer I2 = Retreive(T, 2)
 local integer I3 = Retreive(T, 3)

 call BJDebugMsg(I2S(I))
 call BJDebugMsg(I2S(I2))
 call BJDebugMsg(I2S(I3))

 call FlushAttached(T, 1)
 call FlushAttached(T, 2)
 call FlushAttached(T, 3)
 call PauseTimer(T)
 call DestroyTimer(T)
endfunction

function Test takes nothing returns nothing
 local timer T = CreateTimer()

 call Attach(T, 1, 1005)
 call Attach(T, 2, 1405)
 call Attach(T, 3, 1895)
 call TimerStart(T, 1, false, function Test2)
endfunction

The only real difference is an integer to mark the 'name' of the saved value, rather then a string. But I'd really like some input on the speed, I don't have anything to benchmark it, and I'd like to be sure it's not worse then using something else.
10-04-2007, 02:12 AM#2
Tide-Arc Ephemera
Not that this note is oh-so vital, but you DO know there ARE Jass tags, right?

Code:
[jass]
Insert the code here
Omg my code is so pwn
Blah blah blah
[/jass]
10-04-2007, 02:33 AM#3
Blackroot
I did not, actually. But code is so much prittier! :D

And I realized that this won't be very effective, it caps out at 8190 variables, and because there's no way to destroy or reset them, the cap means you could use only 8190 over the lifetime of the cache. Working on a fix now.

*Added a flush function, as long as you correctly flush the values when you are done, you should never reach the 8190 limit.
10-04-2007, 03:17 AM#4
Vexorian
It would be good, if it wasn't for the fact it doesn't scale correctly.

For example, if you had 200 things using this system, you would need 200 array accesses each time your functions are called, this is pretty much ultra slower than gamecache.

Many things have been done already, I am going to promote tries because they are cool, you probably can find examples of "substraction" which involves substracting min_handle_index from H2I and then accessing that array index...

Some have made a hash table in Jass, that one also works...

If you want the truth, gamecache should be fine provided you only use it for one thing per cycle and only attach integers to units...
10-04-2007, 04:38 AM#5
Blackroot
That's a good point, but I can't get around, how does a gamecache work? I mean, the only way I'd see it working is to check each string the same way I checked integers. But that's not the case, at least I don't think.

Flush is incredibly slow though, I might try some other method. Gah, if only you could have infinite arrays, you could just set the integer handle to a fake 'pointer' structure which holds you information on saved values.

[edit]
And an attempt at handle subtraction, like you suggested:
Collapse JASS:
function H2I takes handle h returns integer
 return h
 return 0
endfunction

globals
 integer array CacheSystem
endglobals

struct CacheValues
 integer value
endstruct

function CacheInt takes handle hv, integer val returns integer
 local CacheValues cv = CacheValues.create()
 local integer hndl = H2I(hv) - 1048708

 if(hndl > 8192 or hndl < 0)then
  return 0
 endif

 set cv.value = val
 set CacheSystem[hndl] = cv

 return 1
endfunction

function GetCachedInt takes handle hv returns integer
 local CacheValues cv
 local integer hndl = H2I(hv) - 1048708

 set cv = CacheSystem[hndl]
 
 return cv.value
endfunction

function FlushCachedInt takes handle hv returns nothing
 local CacheValues cv
 local integer hndl = H2I(hv) - 1048708

 set cv = CacheSystem[hndl]
 call cv.destroy()
endfunction
That was what I was trying to do from the start, but I didin't know how to reduce a handle to 0. I just created a few handles and found they're just linear +1/handle. Easy.

Just a few things though, It doesn't work for units, and I'm not sure what else. But units have custom values, so there shoulden't be anything you can't attach. This only works for a single value though. Not neccesarialy a problem if you use structs. Although, I'm intending to add indexing and unit support, but it's much fast then my old heap. Just one question though, will the handles recycle correctly? I dont want to hit the array limit with something I can't control, after all.
10-04-2007, 06:35 AM#6
Anitarf
Just look at CSCache, it comes with the caster system, and has this already implemented, with the added bonus of resorting to gamecache if ithe indexes get too large (so, if you do something stupid and your handle count goes above 8190, the map doesn't bug, just starts running slower).
10-04-2007, 07:02 AM#7
cohadar
Quote:
Originally Posted by Vexorian
It would be good, if it wasn't for the fact it doesn't scale correctly.

For example, if you had 200 things using this system, you would need 200 array accesses each time your functions are called, this is pretty much ultra slower than gamecache.

Many things have been done already, I am going to promote tries because they are cool, you probably can find examples of "substraction" which involves substracting min_handle_index from H2I and then accessing that array index...

Some have made a hash table in Jass, that one also works...

If you want the truth, gamecache should be fine provided you only use it for one thing per cycle and only attach integers to units...

What are those tries you are talking about all the time,
gimme a link I want to see that.

Attaching to units is ... no comment.

Everybody is making their "systems" these days....
10-04-2007, 09:13 AM#8
Toadcop
Quote:
Everybody is making their "systems" these days....
my days were more than 1 year ago ^^

custom hash alg is MUCH slower than native one. so no sense to use it or to look on it.
10-04-2007, 09:20 AM#9
cohadar
Quote:
Originally Posted by Toadcop
custom hash alg is MUCH slower than native one. so no sense to use it or to look on it.

And that would be true if there was no I2S(H2I(x)) mess.