- Joined
- Jul 10, 2007
- Messages
- 6,306
Ok.... apparently I've been shooting too high on this, rofl... I tried out my tests on KT2 o-o... so... I'm doing good I guess ; ).
KT2 Vs Streams
I bet you would love to see this now wouldn't you : ), but I respect jesus4lyf so I'm not going to say the results =).
Streams (Timers) Vs Streams (Task Manager)
So what's the difference between these two? One uses Blizzard's Timers for Tasking timers and firing things off. The other uses its own custom task manager (runs on one timer ^_^).
Both are pretty much same speed... they lagged at the same rates ^_^; however, the Task Manager version still needs work (a bit complicated). The task manager version might also crash (stop working) on large sets of timers (like 7k+). The reason is because of the looping in it : ).
Both of them are hella faster than plain old timers when using the same periods. They also use precision to merge streams (timers) of the same period that are close to each other. The lower the precision, the less it merges. 0 is 0 merger unless they on exact same time =). The higher the period, the more the merges, and the more the performance, but the less accurate your first tick.
Both of them use data blocks as units. The data block size is that of the STREAM_RATE variable.
Stream Timers Version is a later version, so it uses definition overloading on the functions to make it nicer =), but this'll get introduced to Task Manager version as well.
The Stream Timers version is not that big... not even 200 lines with comments o-o. The Task Manager version is double size : p.
Uh... yea... so you can try them both out I suppose..
Oh yes.. and both of them beat out everything on data attachment : D. SetupStream must be called on both of them (to set your stream up), or the stream dies : (.
So... without further ado, v4.3 of Task Manager of v1.0 of Timers : D.
Timers Demo Code
Task Manager Demo Code isn't out because the Task Manager syntax is going to change to match Timers ^^
The Task Manager
Timers
KT2 Vs Streams
I bet you would love to see this now wouldn't you : ), but I respect jesus4lyf so I'm not going to say the results =).
Streams (Timers) Vs Streams (Task Manager)
So what's the difference between these two? One uses Blizzard's Timers for Tasking timers and firing things off. The other uses its own custom task manager (runs on one timer ^_^).
Both are pretty much same speed... they lagged at the same rates ^_^; however, the Task Manager version still needs work (a bit complicated). The task manager version might also crash (stop working) on large sets of timers (like 7k+). The reason is because of the looping in it : ).
Both of them are hella faster than plain old timers when using the same periods. They also use precision to merge streams (timers) of the same period that are close to each other. The lower the precision, the less it merges. 0 is 0 merger unless they on exact same time =). The higher the period, the more the merges, and the more the performance, but the less accurate your first tick.
Both of them use data blocks as units. The data block size is that of the STREAM_RATE variable.
Stream Timers Version is a later version, so it uses definition overloading on the functions to make it nicer =), but this'll get introduced to Task Manager version as well.
The Stream Timers version is not that big... not even 200 lines with comments o-o. The Task Manager version is double size : p.
Uh... yea... so you can try them both out I suppose..
Oh yes.. and both of them beat out everything on data attachment : D. SetupStream must be called on both of them (to set your stream up), or the stream dies : (.
So... without further ado, v4.3 of Task Manager of v1.0 of Timers : D.
Timers Demo Code
Task Manager Demo Code isn't out because the Task Manager syntax is going to change to match Timers ^^
JASS:
include "cj_types.j"
include "cj_typesEx.j"
include "cj_print.j"
include "cj_types_priv.j"
include "cj_typesEx_priv.j"
include "cj_order.j"
include "cj_antibj_base.j"
scope Demo initializer Initialization {
int loops
int i = 1
int size = 0
trigger t = CreateTrigger()
timer ti = CreateTimer()
bool Test() {
Stream.setup
printf(I2S(Stream.get))
return false
}
bool Setup() {
loops = 1
do {
//TimerStart(CreateTimer(), ++size*.0125, true, function Test)
size += 32
Stream.add(size, function Test, 0)
//KT_Add(function Test, 5, ++size*.0125)
} whilenot --loops == 0
return false
}
void Initialization() {
TriggerAddCondition(t, Condition(function Setup))
do {
TriggerEvaluate(t)
} whilenot --i == 0
}
}
The Task Manager
JASS:
library Stream initializer Initialization {
/*System Information
//===================================================================
Name: Streams (Task Manager)
Version: 4.3
Author: Nestharus
Settings:
*///===================================================================
globals
private constant real STREAM_RATE = .03125
private constant int PRECISION = 1
endglobals
/*//===================================================================
Description:
This is a very fast and efficient timer system that runs on two timers, or known as streams.
One timer deals with whole numbers and the other timer deals with smaller numbers.
Requirements: None
Installation: NA
Variables:
-STREAM_RATE
How many often the stream runs. The bigger the bit rate,
the more accurate your timers can be. .03125 is a good value.
-PRECISION
How precise streamed code is. The smaller the value, the more precise, but the more
streams. The less precise, the less stream and higher performance. 0 is maximum precision.
Each precision is 1 stream block (STREAM_RATE).
Functions:
------------------------------------------------------------------
-public int AddCode(int period, code c, int data)
Will put code into the system. Returns a unique stream.
-public void RemoveCode()
-public void RemoveStreamCode(Stream theStream)
Will remove a specific or current running stream from the system
-public constant int GetAge()
-public constant int GetStreamAge(Stream theStream)
Will get the age of a specified or current running strema.
-public constant int GetTime()
-public constant int GetStreamTime(Stream theStream)
Will get timeout of a specified or current running stream
-public constant int GetStream()
Will get the current running stream
-public void SetData(int value)
-public void SetStreamData(Stream theStream, int value)
Set data on a specified or current running stream
-public int GetData()
-public int GetStreamData(Stream theStream)
Get data for a specified or current running stream
-public constant int GetInterval()
-public constant int GetStreamInterval(Stream theStream)
Returns a master stream's interval. Will automatically retrieve the master stream
that a stream is on.
-public void SetStreamInterval(Stream theStream, int value)
-public void SetInterval(int value)
Will forcefully set a master stream's interval and will take effect on next tick.
This will change all streams on the master stream. To change a time out, you should
remove the stream and re-add it into the system! This can also cause two master streams
to have the same value. Be careful with this function.
-public constant int GetRemainingTime(Stream theStream)
Will return the remaining time of a given stream
-public int R2B(real r)
Will convert a real time into a stream block for use in the system
------------------------------------------------------------------*/
//===================================================================
private int time = 0
public keyword RunStack
private struct Stream extends array {
public Stream last
public int birth
public int interval
public Stream master
public Stream next
public Stream previous
public int data
public triggercondition conditionCode
public trigger runStream
public RunStack stack
public int size
}
public struct RunStack extends array {
public static int index = 0
public static int array stack
public static int stackIndex = 0
public static RunStack current = 0
public static RunStack last = 0
public int time
public RunStack previous
public RunStack next
public Stream data
}
private int array streamStack
private int streamStackIndex = 0
private int streamIndex = 0
public Stream stream
private Stream masterStream = 0
public RunStack runStack = 0
public int i
private int i2
private int i3
private bool fin = false
private hashtable streams = InitHashtable()
private timer streamProcess = CreateTimer()
define SetupStream = {
if Stream_stream == -1 {Stream_stream = Stream_RunStack(Stream_i).data.next}
else {Stream_stream = Stream_stream.next}
}
public int GetData() {
return stream.data
}
public void SetData(int value) {
stream.data = value
}
public constant int GetStream() {
return stream
}
public constant int GetTime() {
return time
}
public constant int GetRemainingTime(Stream theStream) {
return theStream.master.stack.time - time
}
public constant int GetAge() {
return time - stream.birth
}
public constant int GetInterval() {
return stream.master.interval
}
public void SetInterval(int value) {
stream.master.interval = value
}
public void RemoveCode() {
RELEASE_STREAM(stream)
TriggerRemoveCondition(stream.runStream, stream.conditionCode)
stream.data = 0
REMOVE_STREAM(stream)
}
public int GetStreamData(Stream theStream) {
return theStream.data
}
public void SetStreamData(Stream theStream, int value) {
theStream.data = value
}
public int R2B(real r) {
return R2I((r/STREAM_RATE)+.5)
}
public constant int GetStreamTime(Stream theStream) {
return theStream.master.stack.time
}
public constant int GetStreamAge(Stream theStream) {
return time - theStream.birth
}
public void RemoveStreamCode(Stream theStream) {
RELEASE_STREAM(theStream)
TriggerRemoveCondition(theStream.runStream, theStream.conditionCode)
theStream.data = 0
REMOVE_STREAM(theStream)
}
public constant int GetStreamInterval(Stream theStream) {
return theStream.master.interval
}
public void SetStreamInterval(Stream theStream, int value) {
theStream.master.interval = value
}
define private NEW_STREAM_STACK(streamName) = {
if RunStack.stackIndex != 0 {
streamName = RunStack.stack[RunStack.stackIndex--]
}
else {
streamName = ++RunStack.index
}
}
define private NEW_STREAM(streamName) = {
if streamStackIndex != 0 {
streamName = streamStack[streamStackIndex--]
}
else {
streamName = ++streamIndex
}
}
define private RELEASE_STREAM(streamName) = {
streamStack[++streamStackIndex] = streamName
}
define private REMOVE_STREAM(streamName) = {
if streamName.last == streamName {
streamName.master.last = streamName
}
streamName.previous.next = streamName.next
streamName.next.previous = streamName.previous
streamName.master.size--
if streamName.master.size == 0 {
RemoveSavedInteger(streams, masterStream.interval, masterStream.birth - (masterStream.birth - masterStream.interval))
masterStream = streamName.master
RELEASE_STREAM(masterStream)
DestroyTrigger(masterStream.runStream)
masterStream.stack.next.previous = masterStream.stack.previous
masterStream.stack.previous.next = masterStream.stack.next
if RunStack.current == masterStream.stack {
RunStack.current = RunStack.current.next
RunStack.current.previous = 0
}
if RunStack.last == masterStream.stack {
RunStack.last = RunStack.last.previous
RunStack.last.next = 0
}
RunStack.stack[++RunStack.stackIndex] = masterStream.stack
}
}
define private RUN_STREAM_STACK_NEW(runStackNew) = {
if RunStack.current == 0 {
RunStack.current = runStackNew
RunStack.last = runStackNew
runStackNew = runStackNew
runStackNew = runStackNew
runStack.time = masterStream.interval + time
fin = true
}
}
define private RUN_STREAM_STACK_DO_GREATER_THAN(runStackOld, runStackNew) = {
if runStackOld.data.interval+time >= masterStream.interval + time {
if runStackOld.previous != 0 {
runStackNew.previous = runStackOld.previous
runStackOld.previous.next = runStackNew
}
else {
RunStack.current = runStackNew
}
runStackOld.previous = runStackNew
runStackNew.next = runStackOld
}
}
define private RUN_STREAM_STACK_DO_LESS_THAN(runStackOld, runStackNew) = {
if runStackOld.data.interval+time <= masterStream.interval + time {
if runStackOld.next != 0 {
runStackNew.next = runStackOld.next
runStackOld.next.previous = runStackNew
}
else {
RunStack.last = runStackNew
}
runStackNew.previous = runStackOld
runStackOld.next = runStackNew
}
}
define private RUN_STREAM_STACK_GREATER_THAN(runStackOld, runStackNew) = {
if runStackOld.data.interval+time > masterStream.interval + time {
i = runStackOld
whilenot RunStack(i).previous.data == 0 || RunStack(i).data.interval+time >= masterStream.interval + time {
i = RunStack(i).previous
}
RUN_STREAM_STACK_DO_GREATER_THAN(RunStack(i), runStackNew)
RUN_STREAM_STACK_DO_LESS_THAN(RunStack(i), runStackNew)
runStackNew = runStackNew
runStackNew = runStackNew
runStack.time = masterStream.interval + time
fin = true
}
}
define private RUN_STREAM_STACK_LESS_THAN(runStackOld, runStackNew) = {
if runStackOld.data.interval+time < masterStream.interval + time {
i = runStackOld
whilenot RunStack(i).next == 0 || RunStack(i).data.interval+time >= masterStream.interval + time {
i = RunStack(i).next
}
i = RunStack(i)
RUN_STREAM_STACK_DO_GREATER_THAN(RunStack(i), runStackNew)
RUN_STREAM_STACK_DO_LESS_THAN(RunStack(i), runStackNew)
runStackNew = runStackNew
runStackNew = runStackNew
runStack.time = masterStream.interval + time
fin = true
}
}
public int AddCode(int period, code c, int data) {
fin = false
i2 = PRECISION*-1
do {
i = LoadInteger(streams, period, time-(time-period)+i2)
i2++
} whilenot i != 0 || i2 == PRECISION
if i == 0 {
fin = false
NEW_STREAM(masterStream)
masterStream.master = masterStream
masterStream.last = masterStream
masterStream.interval = period
masterStream.birth = time
masterStream.runStream = CreateTrigger()
SaveInteger(streams, period, time-(time-period), masterStream)
NEW_STREAM_STACK(runStack)
RUN_STREAM_STACK_NEW(runStack)
if !fin {
RUN_STREAM_STACK_GREATER_THAN(RunStack.current, runStack)
}
if !fin {
RUN_STREAM_STACK_LESS_THAN(RunStack.current, runStack)
}
masterStream.stack = runStack
runStack.data = masterStream
}
else {
masterStream = i
}
NEW_STREAM(stream)
masterStream.last.next = stream
stream.previous = masterStream.last
masterStream.last = stream
stream.master = masterStream
stream.birth = time
stream.conditionCode = TriggerAddCondition(masterStream.runStream, Condition(c))
masterStream.size++
stream.data = data
return stream
}
private void StreamProcess() {
time++
if RunStack.current.time == time {
if RunStack.current.next != 0 {
i = RunStack.current
runStack = RunStack(i).next
do {
stream = -1
TriggerEvaluate(RunStack(i).data.runStream)
RunStack(i).time = RunStack(i).data.interval + time
i3 = RunStack(i).next
runStack = i2
if (RunStack(i).time < runStack.time && RunStack(i).time < runStack.previous.time) {
runStack = RunStack(i).next
}
whilenot RunStack(i).time < runStack.time || runStack.next == 0 {
runStack = runStack.next
}
if RunStack(i).next != runStack {
if RunStack(i).time <= runStack.time {
runStack.previous.next = i
RunStack(i).previous.next = RunStack(i).next
RunStack(i).next.previous = RunStack(i).previous
RunStack(i).previous = runStack.previous
runStack.previous = i
RunStack(i).next = runStack
}
else {
RunStack(i).previous.next = RunStack(i).next
RunStack(i).next.previous = RunStack(i).previous
RunStack(i).next = runStack.next
RunStack(i).previous = runStack
runStack.next = i
}
if RunStack(i) == RunStack.current {
RunStack.current = i3
}
if runStack == RunStack.last {
RunStack.last = i
}
}
i2 = i
i = i3
} whilenot RunStack(i).time != time
}
else {
stream = -1
i = RunStack.current
TriggerEvaluate(RunStack.current.data.runStream)
RunStack.current.time = RunStack.current.data.interval + time
}
}
}
private void Initialization() {
stream = -1
TimerStart(streamProcess, STREAM_RATE, true, function StreamProcess)
}
}
Timers
JASS:
library Stream initializer Initialization uses GameTime, Recycle {
/*System Information
//===================================================================
Name: Streams (Timers)
Version: 1.0
Author: Nestharus
Settings:
*///===================================================================
globals
public constant real STREAM_RATE = .03125
private constant int PRECISION = 1
endglobals
/*//===================================================================
Description:
A timer system that merges timers into master streams.
Requirements: None
Installation: NA
Variables:
-STREAM_RATE
Size of a block in a stream
-PRECISION
How precise streamed code is. The smaller the value, the more precise, but the more
streams. The less precise, the less stream and higher performance. 0 is maximum precision.
Functions:
------------------------------------------------------------------
Methods/Operators
-Stream.add(int period, code c, int data)
Will put code into the system. Returns a unique stream.
-Stream.remove()
-Stream.removeStream(Stream theStream)
Will remove a specific or current running stream from the system
-Stream.getAge
-Stream.getAge(theStream)
Will get the age of a specified or current running strema.
-Stream.getTime
-Stream.getTime(Stream theStream)
Will get timeout of a specified or current running stream
-Stream.getRemaining
-Stream.getRemaining(Stream theStream)
Will get remaining time of a specified or current running stream
-Stream.get()
Will get the current running stream
-Stream.setData(value)
-Stream.setData(theStream, value)
Set data on a specified or current running stream
-Stream.getData
-Stream.getData(theStream)
Get data for a specified or current running stream
-Stream.getInterval()
-Stream.getInterval(Stream theStream)
Returns a master stream's interval. Will automatically retrieve the master stream
that a stream is on.
-Stream.R2B(real r)
Will convert a real time into a stream block for use in the system
-Stream.Setup
Sets the stream up. Must be called on all timer functions
------------------------------------------------------------------*/
//===================================================================
private int time = 0
public Stream stream = -1
public Stream masterStream = 0
public int i = 0
private int timeout
private boolexpr streamSetup
private hashtable streams = InitHashtable()
struct Stream extends array {
public static int array stack
public static int index = 0
public static int stackIndex = 0
public Stream master
public int interval
public Stream previous
public Stream next
public Stream last
public triggercondition conditionCode
public trigger runStream
public timer runStreamTimer
public int birth
public int data
public static void remove() {
ReleaseStream(stream)
TriggerRemoveCondition(stream.runStream, stream.conditionCode)
stream.data = 0
RemoveStream(stream)
}
public static void removeStream(Stream theStream) {
ReleaseStream(theStream)
TriggerRemoveCondition(theStream.runStream, theStream.conditionCode)
theStream.data = 0
RemoveStream(theStream)
}
define private NewStream(streamName) = {
if Stream.stackIndex != 0 {
streamName = Stream.stack[Stream.stackIndex--]
}
else {
streamName = ++Stream.index
}
}
public static bool StreamSetup() {
time = R2I(GetElapsedGameTime()*STREAM_RATE)
timeout = R2I(TimerGetTimeout(GetExpiredTimer())/STREAM_RATE)
stream = LoadInteger(streams, timeout , time-(time-timeout))
return false
}
public static int add(int period, code c, int data) {
i = PRECISION*-1
time = R2I(GetElapsedGameTime()*STREAM_RATE)
do {
masterStream = LoadInteger(streams, period, time-(time-period)+i)
i++
} whilenot integer(masterStream) != 0 || i == PRECISION
if integer(masterStream) == 0 {
NewStream(masterStream)
masterStream.last = masterStream
masterStream.interval = period
masterStream.birth = time
masterStream.runStream = CreateTrigger()
masterStream.runStreamTimer = Timer.get()
TriggerRegisterTimerExpireEvent(masterStream.runStream, masterStream.runStreamTimer)
TriggerAddCondition(masterStream.runStream, streamSetup)
TimerStart(masterStream.runStreamTimer, I2R(period)*STREAM_RATE, true, null)
SaveInteger(streams, period, time-(time-period), masterStream)
}
NewStream(stream)
masterStream.last.next = stream
stream.previous = masterStream.last
masterStream.last = stream
stream.master = masterStream
stream.birth = time
stream.conditionCode = TriggerAddCondition(masterStream.runStream, Condition(c))
stream.data = data
return stream
}
}
define {
<Stream.getData> = Stream_stream.data
<Stream.getData>(theStream) = Stream_Stream(theStream).data
<Stream.setData>(value) = Stream_stream.data
<Stream.setData>(theStream, value) = Stream_Stream(theStream) = value
<Stream.get> = Stream_stream
<Stream.getAge> = GetElapsedGameTime() - I2R(Stream_stream.birth)/STREAM_RATE
<Stream.getAge>(theStream) = GetElapsedGameTime() - I2R(Stream_Stream(theStream).birth)/STREAM_RATE
<Stream.R2B>(realVal) = R2I((realVal/Stream_STREAM_RATE)+.5)
<Stream.getTime> = TimerGetElapsed(Stream_stream.master.runStreamTimer)
<Stream.getTime>(theStream) = TimerGetElapsed(Stream_Stream(theStream).master.runStreamTimer)
<Stream.getInterval> = Stream_stream.master.interval
<Stream.getInterval>(theStream) = Stream_Stream(theStream).master.interval
<Stream.getRemaining> = TimerGetRemaining(Stream_stream.master.runStreamTimer)
<Stream.getRemaining>(theStream) = TimerGetRemaining(Stream_stream.master.runStreamTimer)
<Stream.setup> = Stream_stream = Stream_stream.next
}
define private ReleaseStream(streamName) = Stream.stack[++Stream.stackIndex] = streamName
define private RemoveStream(streamName) = {
if streamName.master.last == streamName {
streamName.master.last = streamName.previous
}
streamName.previous.next = streamName.next
streamName.next.previous = streamName.previous
if streamName.master.last == streamName.master {
masterStream = streamName.master
RemoveSavedInteger(streams, masterStream.interval, masterStream.birth - (masterStream.birth - masterStream.interval))
ReleaseStream(masterStream)
DisableTrigger(masterStream.runStream)
TriggerRemoveCondition(masterStream.runStream, masterStream.conditionCode)
DestroyTrigger(masterStream.runStream)
PauseTimer(masterStream.runStreamTimer)
Timer.release(masterStream.runStreamTimer)
}
}
private void Initialization() {
streamSetup = Condition(function Stream.StreamSetup)
}
}
Last edited: