Blitzmax doesn't support more than 16 timers?!

BlitzMax Forums/BlitzMax Programming/Blitzmax doesn't support more than 16 timers?!

GfK(Posted 2006) [#1]
Been bug-hunting for the last couple of hours and it turns out it isn't even my code thats causing the problem.

Turns out Blitzmax cannot have more than 16 timers at once?? I currently need up to 80.

Global timers:TTimer[500]
Global success:Int = 0
Global fail:Int = 0

For n = 0 To 499
	timers[n] = CreateTimer(1)
	If timers[n] = Null
		fail:+1
	Else
		success:+1
	EndIf
Next

Print "Failed: " + fail
Print "Succeeded: " + success



skidracer(Posted 2006) [#2]
Eek, that should be documented.

That is a windows system restriction.

I suggest you look at a single 10ms timer or whatever your minimum period is and have it manage a list of software timers. The linux implementation I think has some suitable code, will look.


GfK(Posted 2006) [#3]
I suggest you look at a single 10ms timer or whatever your minimum period is and have it manage a list of software timers
Rewriting code at the moment to do exactly that. Wish I'd been aware of the limitation from the off, though. Would have saved me a lot of work.

[edit] Actually I think I'll go to sleep since its 3am. These late nights are killing me.

Oh by the way - this problem *might* be loosely (or directly) related to the other problem I was having which I thought was something to do with looped sounds, if I'm trying to trigger sound effects based on non-existent timers.


CS_TBL(Posted 2006) [#4]
Uh whooo, hold it. I can imagine making some gadget that animates something (like a VU meter or something, or animating buttons) Such a custom gadget would have its own timer to update itself. Would this restriction mean only 16 of these custom gadgets could be made?


skidracer(Posted 2006) [#5]
OK, heres some code to test:

Strict

Type TSuperTimer
	Global timerlist:TList=New TList
	Global systemtimer:TTimer
	Global systemtimerevent:TEvent

	Field	_event:TEvent
	Field	_hertz#
	Field	_count
	Field	_millis
	Field	_ticks
	
	Method Stop()
		timerlist.Remove Self
	End Method
	
	Method Create:TSuperTimer( hertz#,event:TEvent=Null )
		InitSystemTimer
		_event=event
		_hertz=hertz
		_millis=MilliSecs()		
		timerlist.AddLast Self
		Return Self
	End Method

	Method Update(ms)
		Local	count
		count=((ms-_millis)*_hertz)/1000
		If count>_count
			_count=count
			_ticks:+1
			If _event
				EmitEvent _event
			Else
				EmitEvent CreateEvent( EVENT_TIMERTICK,Self,_ticks )
			EndIf
		EndIf
	End Method

	Function InitSystemTimer()
		If systemtimer Return
		systemtimerevent=CreateEvent( EVENT_TIMERTICK,Null,0 )
		AddHook EmitEventHook,supertimerhook
		systemtimer=CreateTimer(100,systemtimerevent)
	End Function

	Function supertimerhook:Object( id,data:Object,context:Object )
		Local	ms
		Local	t:TSuperTimer
		If data<>systemtimerevent Return data
		ms=MilliSecs()
		For t=EachIn timerlist
			t.Update(ms)
		Next
	End Function
End Type

Function CreateSuperTimer:TSuperTimer(hertz#,event:TEvent=Null)
	Return New TSuperTimer.Create(hertz,event)
End Function

' test code below

For Local i=1 To 1000
	createsupertimer(10)
Next

While WaitEvent()
	
	DebugLog "tick"+EventData()
Wend



H&K(Posted 2006) [#6]
Here is a link where Mark tells us that he is adding a null return to the seventeenth timer.

http://www.blitzbasic.com/Community/posts.php?topic=64601#721490

The thread was a lot longer, but a lot of it was culled.


Warren(Posted 2006) [#7]
GfK

FYI, my timer module should handle any number of timers without a hassle. Link is in my sig if you're interested...


Mordax_Praetorian(Posted 2006) [#8]
Now I'm glad I decided to make my own timers for my rpg engine


GfK(Posted 2006) [#9]
Thanks for the replies.

I've spent a couple of hours today writing a timer system that's based off a single system timer running at 10hz, the good thing being I can have as many 'software' timers as I like with very little overhead.

I'm not a massive fan of using other people's code. I'd much rather write my own because that way I fully understand what its doing from the outset.

:)


ImaginaryHuman(Posted 2006) [#10]
80 timers? wow.

:-)


Warren(Posted 2006) [#11]
I'm not a massive fan of using other people's code. I'd much rather write my own because that way I fully understand what its doing from the outset.

Understandable. Just presenting an option is all. :)


rdodson41(Posted 2006) [#12]
Gfk I'm just curious, what are you using 80 timers for?


GfK(Posted 2006) [#13]
I have a grid of 72 tiles. Any or all of those tiles may have a bonus attached. Some bonuses have time limits, some don't. So potentially that's 72 timers. Plus I'm using two or three other generally throughout the game.

Managed to get the bonus timers running off a single 10hz timer now - I was just trying to do it the easy way without realising there was a 16 timer limit, because the limitation isn't documented.


Banshee(Posted 2006) [#14]
Question: millisecs() varies with up to +/-5% innacuracy on modern motherboards, and in a few extreme cases a lot more. Do Timers() bypass/correct this in some way? Because i've always used one global time variable 'delta' which I update from the system timer, and then applied that to individual software timers - the introduction of timers() into BMax is still confusing me, because I have to ask 'Why?', and I assume there's some advantage to them in some way other than being IRQ instanced?


Grey Alien(Posted 2006) [#15]
Can't you just make your own timer component that uses Delta timing? That's what I did for my bonus games. I can create as many as I want and manage them globally in a list.


H&K(Posted 2006) [#16]
@Banshee,
Do Timers() bypass/correct this in some way

NO.
At some frequencies its right, but most of the time it cannot be garenteed to have waited the lenght of time you wanted. (but its a piddleing difference, so... not really important.

@GFK, I know you have gone for 10HZ, but why not tie the timer to the screen sycn. OK so you would have a lot of "Null" loops, but you are more lickly to keep sync. I only ask, because I use a timer to flip, so cannot use sync, but if I was fullscreening, then I would concider the screen sync to be my timer and run from that. (if you see what I mean, I either tell the comp when to sync, or take the sycn to tell the program what to do)


GfK(Posted 2006) [#17]
@GFK, I know you have gone for 10HZ, but why not tie the timer to the screen sycn.
The timer is not controlling the frame rate, nor is it related to the frame rate in any other way. I simply can't justify wasting processor time doing 60 updates when 10 will do the same job.


H&K(Posted 2006) [#18]
Fair enough


Dreamora(Posted 2006) [#19]
"wasting processor time" ...
You are aware that you are talking of < 1 ns per second, right?
You think its justified to hack strange non linear code but wasting a ps for linear clean code isn't.

Especially in your case, where you have to redraw the field anyway so updating it (and fire the timer if needed) is no waste at all.

Really strange programming moral.


H&K(Posted 2006) [#20]
Whereas I agree with you Dream, I cannot decry GFK, because if his deign poilicy is to try and cut those ns, then so be it. I never wirte anythig so omplex that i need to worry about ns


GfK(Posted 2006) [#21]
You are aware that you are talking of < 1 ns per second, right?
A waste of 1ms per function is still a waste. A waste of 1ms per function over a hundred functions is a colossal waste.
You think its justified to hack strange non linear code but wasting a ps for linear clean code isn't.
Huh? I haven't hacked anything. What the hell are you talking about?
Especially in your case, where you have to redraw the field anyway so updating it (and fire the timer if needed) is no waste at all.
How can you possibly comment about 'my case' when you don't even know what I'm working on? I'm not being funny but I often get the feeling that you're posting for the sake of typing something.
Really strange programming moral.
Optimising code for maximum execution speed is strange?

I think this thread can be closed now. Problem is sorted.


Warren(Posted 2006) [#22]
Optimising code for maximum execution speed is strange?

If it doesn't matter, yes. Measure first, then optimize.


GfK(Posted 2006) [#23]
If it doesn't matter, yes.
If you want your game to work well on an old/slow PC then optimisation always matters. IMHO.

I generally test almost every function for speed. If a function is taking too long then I need to do something to make it go faster. I consider that normal.


Warren(Posted 2006) [#24]
In general, I agree with you. However, if you're optimizing code that isn't in the critical path (i.e. every frame) you're wasting time IMO. Time that could be spent on some other aspect of the game.


H&K(Posted 2006) [#25]
if you're optimizing code that isn't in the critical path (i.e. every frame) you're wasting time IMO
hahahahahahahahahahahahahaha. Definitaly a case of "read the previous posts"


Warren(Posted 2006) [#26]
Definitaly a case of "read the previous posts"

I was under the impression that we (GfK and I) were talking in the general sense, not related to this specific timer issue.


H&K(Posted 2006) [#27]
soooooo, even though GFK was replying to me, and then dream, about putting somthing in the critical loop or not. You were under the impresion that you and he were still haveing the converstation about your timer code.

OK fair enough,I think I should draw your attention to my previous post
hahahahahahahahahahahahahaha. Definitaly a case of "read the previous posts"



Warren(Posted 2006) [#28]
You've lost me. Doesn't matter.


GfK(Posted 2006) [#29]
I'm lost too. Never mind.


bregors(Posted 2006) [#30]
.


Dreamora(Posted 2006) [#31]
1 ns = 1/ 100 000 millisecond. If you fire your strange function a 100k times per millisecond, then you will have to worry. But if you do so, your update loop is massivle flawed and I don't think that you are doing it :)
You redraw and update your fields most likely at a fixed FPS rate which means 100 times or the like at maximum (if you render it more often: congrats, you worry about ns but waste massive amounts of time *XX ms per frame) to have 300FPS instead of 100 which is the max of screens? ... with the other 200 FPS you could easiely have a tousand times larger calculation time frames than you currently have :) ), so definitely no problem.

Especially as it was mentioned that it should be optimized for low end machines ... those machines most likely won't be too happy with hundreds of hardware timers at all. They are already slow and have far slower access and reaction times then your system. How do you think will they react to that many timers? :)

There are some threads on general optimations that are far more powerfull than such milli - micro - nano - second hacks which in the end just complicate the code without giving enough boost to justify them (primary target of code is reusability and stability, not 1ns faster for 3 hours longer to understand and extend).

Generally, the following things make a massive difference:

Object pooling: As some might have read, I've added this to ParticleDreams to for testing. Result is a speed gain of over 500% or from 7000-8000 particles to over 30'000.
This is one of the most important things at all.
With many dynamic objects of a given type, it is essential that they are pooled instead of created and destroyed all the time!

Rendering: Don't render more often than the screen actually supports it. It just costs time that your game logic could have used. There is the common misassumption, that a game running at 300 FPS is better than a game running at 100FPS, but to me on notebook TFT with 60 FPS, both just waste hundreds of millisecs each second which do not get me anything. Ask the user for his desired FPS (as UT did) and only render at that rate. Use the saved rendering time for maths, AI or networking, as well as more sophisticated effects, collision and physics.


Array vs TList vs TMap:
Its very important to understand the pro and cons of each of those (especially of the new TMap implementation which is like day and night compared to the old one!) and how they are used most efficiently.
For example, many users forget to save the TLink that is returned from someList.addlast in their object classes for fast removal from the list and the like. This makes large differences, the larger the lists get. (was another optimation to PD2 which made a large diff. in the original version this was impossible as TLinks were not stable back then)


GfK(Posted 2006) [#32]
Well, thanks for that lesson in 'good coding' which I seem to have got through the last two and a half decades without.

Maybe you should start a new thread instead of taking this one further still off topic.


Banshee(Posted 2006) [#33]
NO.
At some frequencies its right, but most of the time it cannot be garenteed to have waited the lenght of time you wanted. (but its a piddleing difference, so... not really important.

It's hugely important in multiplayer games though, syncronising innacurate millisecs() reports over different machines to match game speed and not provide an advantage, in say, a racing game... I'm interested in any technique that can make syncronised network time simpler, but i'm not convinced this is it sadly - although i'd have liked it to be :).

As for dynamic objects - yah, makes a huge difference - but mostly I try to stick to instancing now - so I only have 1 copy of a mesh loaded. Of course, that depends entirely upon 3D engine as to whether it's possible... :) Oh B3D why are you so out of date !? :)


Oddball(Posted 2006) [#34]
I agree...

The fact that 16 timers is the maximum should be documented.