PDA

View Full Version : stuttering movement



zed
03-21-2011, 09:41 PM
Im talking about movement of objects on the screen
Is anyone else seeing this?

If I use deltatime & a single update & then render, its smooth
but for most of my stuff I like to have a fixed loop for updates (plays nice with physics etc)
& a render per frame, but its often jerky.

Yes Im lerping from previous position to current position using the remaining time left over from the update (OK so theres a little lag but it should be smooth).

Now Ive written countless applications in C++ etc & never had this issue before
but now with webgl its affecting all my applications.
Im not 100% sure what could be causing it, Im guessing the timer aint actually 100% correct with javascript, but it could also be webgl related

is there another method of obtaining system time than Date()?
Or does anyone have any ideas how to fix this

ta Zed

SteveBaker
03-22-2011, 06:16 AM
I've been having similar problems - and I tracked my issues down to garbage collection.

YMMV - but this seems to be a common (and growing) problem. As JavaScript programs get larger, the time it takes for a garbage collection cycle gets longer and longer.

I thought that the approach that garbage-collecting languages took was to wait until memory was running low - and then take out the trash. That would give you a glitch once in a while - but presuming you're not going nuts with dynamic memory allocation, you'd hope it would be rare. But that's not what happens in practice. I've been getting a garbage collect cycle happening once every two or three seconds!

The problem with garbage collection is that the time it takes increases with the size of the program - and takes exponentially more time as your data structures get more complex. What seems like a reasonable approach for a typical web site with a few hundred lines of JavaScript that only runs when you click on something - starts to look like a major disaster with 10,000 line programs that loop on timers thirty times a second.

Knowing this, I'd been pretty careful not to do dynamic allocations - but it seems that I wasn't careful enough!

When I looked through my code, I found I had missed just TWO short-term allocations per iteration of my main rendering loop. Those were in a matrix library where it was making a new temporary matrix in order to store intermediate results. When I changed that to use a global variable instead - all of my glitches smoothed out and the program runs smooth as silk!

Clearly the system isn't waiting until it runs low on memory before it collects garbage...there is no way I'm within a few hundred bytes of running out of RAM! The precise nature of the algorithm isn't well described anywhere I can find - but it seems that the Firefox garbage collector uses some kind of heuristic to figure out when to collect...and somehow, my two allocations of maybe a couple of hundred bytes per frame 'tickled' the heuristic and caused a collection cycle every few seconds.

Of course now I have to test under Chrome and Safari to be sure they are also happy - but I suspect they'll be OK too.

Basically, this means that you can't risk doing even a single byte of dynamic memory allocation ANYWHERE in your main loop. It's insanely annoying.

JavaScript is a really terrible programming language for realtime graphics!

-- Steve

zed
03-22-2011, 11:59 AM
cheers Steve, Im not 100% sure if its GC. i.e. if I go

A/
Update()
Render() with dt

its smooth, but it isnt with

B/
accumulator += frameTime;
while ( accumulator >= dt ) {
Update();
accumulator -= dt;
}
Render( accumulator / dt );

// method B does 0->2 updates per frame whereas method A does a single update per frame.

If its GC wouldnt it affect both methods,
Ive done method B with lots of C++ opengl apps & never had an issue, also I tried it with a simple canvas app & it was smooth.

Does anyone know of any 'arcade' (i.e. u control a spaceship/character onscreen) games running under webgl so I can see if they suffer from the same issue?

But youre right about the GC. it would be so nice to have a function where you could call it eg at the end of a level & say clean up the GC now. Ill have another look tonight through my code to see if I am allocating any temporaries

SteveBaker
03-22-2011, 01:43 PM
Actually - there IS a way to force a garbage collection...but that doesn't seem to help...at least not in my case.

https://developer.mozilla.org/En/Compon ... ls.forceGC (https://developer.mozilla.org/En/Components.utils.forceGC)

For me, it was trying to GC every couple of seconds! Forcing it to do one only delayed the inevitable a couple of seconds later.

There is also talk of a "(C++) XPCOM object" collector that runs some separate system from the JavaScript garbage collector...I have no idea what that is or what (if anything) to do about it.

-- Steve

oak3d
03-22-2011, 06:37 PM
Totally agreed with this line:
JavaScript is a really terrible programming language for realtime graphics!

oak3d
03-23-2011, 12:17 AM
I think future webapps will need a more powerful client-side script language.
May be a c#-like or java-like language is good.
Javascript's flexibility is a disaster for large project.

SteveBaker
03-23-2011, 05:33 AM
Trouble is - both C# and Java require garbage collection...so they don't solve the problem.

That's a serious issue. Garbage collecting systems (by their very nature) cause random temporal glitches that are really unacceptable for games and other high-demand interactive systems.

Languages like C++ require programmers to remember to free up memory as needed - which allows one to completely avoid those kinds of glitches. But C++ tends to result in some programmers failing to clean up carefully enough - so you get memory leaks and code that accesses prematurely free'd memory.

JavaScript (and Java and C#) are great for sloppy, clueless amateurs because they make it possible to write carelessly - and nothing too terrible goes wrong. But for programmers who know what they are doing - and who care enough to "get it right" - the unavoidability of garbage collection glitches is a barrier to turning out a quality product - no matter how hard you try. C++ is harder - but it does allow perfection.

What's really needed is a language with built-in reference counting...but there are problems with that too - circular references cause memory leaks.

-- Steve

zed
03-23-2011, 11:35 AM
Actually - there IS a way to force a garbage collection...but that doesn't seem to help...at least not in my case.well force it, but in the meantime dont garbage collect at all. 8)
javascript desperately needs static datatyping, I see its been penciled in for the next release, but who knows when thats gonna happen?
On a related note, Anyone know where to find info about whats happening with google chrome, eg when web audio is expect to make an appearance for windows/linux, its already out for mac. Is there some developer website/newsgroup/forum apart from this where I can find this info. http://blog.chromium.org/

ta zed

zed
03-23-2011, 02:20 PM
actually a nice browser debugging option would be to actually see what its garbage collecting.
This would be extremely useful to clean up/optimize your code.

Does anyone know if such a thing possible with firefox/chrome?

SteveBaker
03-23-2011, 03:35 PM
The problem isn't so much what it's cleaning up as what's triggering it to start up in the first place.

oak3d
03-23-2011, 07:09 PM
How about creating all the small but frequently used objects from a resouce pool, and free the object is just return it back to the pool. The referrence of such objects will never be 0 so the gc of javascirpt will never be trigered.

SteveBaker
03-24-2011, 06:38 AM
Yeah - I'm doing essentially that already. I maintain arrays of objects that can be marked as "free" or "in use" - and instead of new'ing and deleting, I just flag them. However, if I temporarily need 1000 objects - then only two thereafter, then a lot of memory is wasted.

But it's better than nothing.

My problem was actually due to some code hiding down inside a third party matrix library that I hadn't looked at carefully enough. I've since rewritten that code.

I suspect though that there are things that I may be doing that causes memory to be allocated and free'd in other ways though...stuff like closures are notorious for this kind of 'parasitic' allocation...I'm not using any of those - but I worry about what other hidden stuff there is out there.