Blitzmax doesn't support more than 16 timers?!
BlitzMax Forums/BlitzMax Programming/Blitzmax doesn't support more than 16 timers?!
| ||
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 |
| ||
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. |
| ||
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. |
| ||
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? |
| ||
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 |
| ||
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. |
| ||
GfK FYI, my timer module should handle any number of timers without a hassle. Link is in my sig if you're interested... |
| ||
Now I'm glad I decided to make my own timers for my rpg engine |
| ||
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. :) |
| ||
80 timers? wow. :-) |
| ||
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. :) |
| ||
Gfk I'm just curious, what are you using 80 timers for? |
| ||
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. |
| ||
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? |
| ||
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. |
| ||
@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, 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. |
| ||
Fair enough |
| ||
"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. |
| ||
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 |
| ||
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. |
| ||
Optimising code for maximum execution speed is strange? If it doesn't matter, yes. Measure first, then optimize. |
| ||
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. |
| ||
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. |
| ||
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" |
| ||
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. |
| ||
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" |
| ||
You've lost me. Doesn't matter. |
| ||
I'm lost too. Never mind. |
| ||
. |
| ||
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) |
| ||
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. |
| ||
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 !? :) |
| ||
I agree... The fact that 16 timers is the maximum should be documented. |