Tuesday, August 23, 2011

jsStruct: C-style struct reading in Javascript

Protip: I ramble a lot before getting to the link in question. You probably just want to jump straight to the project.

So in case you haven't picked up on it yet I tend to work with a lot of binary files in Javascript. This is, to put it kindly, an absolute mess. (I would put it unkindly, but this is a family friendly blog!)

Now, to the credit of the browser makers, binary parsing has certainly gotten a lot better in a very short period of time. When I was doing my Quake 2 and Quake 3 demos, the only way to parse binary was to request you file as a raw string from the server and use String.charCodeAt() to grab the bytes one by one and reconstruct them into the appropriate data types. This meant that parsing a float looked like this:

Saturday, August 20, 2011

Another Teaser Time!

So, I figured I'd post another teaser image. I'm not 100% sure that this is going to work out, but it's certainly turning into a fun project! Hopefully I can have it ready for onGameStart in September, as I think it would make quite an impression!

[UPDATE: See the exciting conclusion!]

Wednesday, August 10, 2011

Hey, Chrome! Fix your texture uploads!

I've been poking and prodding at my RAGE demo as onGameStart draws nearer, trying to clean up the code and squeeze a bit more performance out of it. During this testing I've made a depressing observation:

Chrome's performance, in reference to speed of texture upload, sucks. And by "sucks", I mean as it atrociously, painfully, unforgivingly slow.

The most technically demanding aspect of the RAGE demo is the constant texture swapping that happens every few steps. We pre-allocate an array of 30-40 some 1024x1024 textures (exact number depends on the map) and as we progress along the path we identify upcoming textures that will be needed, download them, and push them into an unused texture, hopefully well before that texture is actually needed. The Webkit and Firefox nightlies can handle this fine (though we do drop a frame or two here or there) but Chrome 14 on my Mac basically breaks down and cries when asked to do this. You can see for yourself in my simple jsperf benchmark.

So, to put this in perspective: Chrome is able to squeak out a measly 22 texture uploads per second at 1024x1024. That's ~50ms per upload that your browser is blocked on that call. If you are shooting for a 60hz game (~16ms per frame) this means that uploading one texture to graphics memory just caused you to drop 3-4 frames. One texture, 3-4 frames lost. Ouch! For a medium that will be highly dependent on streaming, that hurts!

By comparison, Safari 5 gives me 62 uploads per second (ie: you may drop a frame here and there, but performance will stay pretty solid.) and Firefox 7 blasts out a whopping 188 uploads per second! That's ~8ms per upload, leaving lots of breathing room for rendering!

It's a real shame too, because in most other ways Chrome seems to be the most solid performer with WebGL. If I chop all the textures in my RAGE demo down to 512x512 I can run at a rock solid 60hz with no tearing or stuttering. (Though the texture upload is still painfully slow compared to the other browsers.)

Maybe the benchmarks look a lot better on Windows, but I don't have a machine to test that with right now. Regardless, this is something that the Chrome team really needs to smooth out. Pretty please?

(All timing is taken from my iMac)

[UPDATE: I wrote up a bug report on the issue, lets see if it goes anywhere. Similar reports have been added in the past, as seen in the comments on this post]

Monday, August 8, 2011

WebGL Frameworks are awesome, here's why I don't use them.

Tonight I was posed a very interesting question by @HunterLoftis on twitter:

What's your opinion on three.js, glge, etc? I haven't seen anything in that camp half as performant as your quake 3 fullscreen demo

I answered him with my < 140 char assessment of the situation:

I think they're great frameworks, but I question if a high-performance WebGL app can afford the overhead.

I feel like this is a subject that could use a bit more explanation, though, because it's not at all black and white.

Saturday, August 6, 2011

Getting cozy with GitHub

When I posted my code for the WebGL Rage demo, I was quite surprised at the number of comments that I got requesting that I out the code up at GitHub instead of Google Code. At the time I mentioned that I would do so, but then promptly got caught up in the chaos that accompanies relocating to a new job, and never got around to moving the code. (Sorry about that!)

A nice side effect of the delay, however, is that I've gotten quite comfortable with git in the meantime, since that's what I use at my new job! I'm still probably more of a fan Mercurial due to simplicity of the interface, but I've found myself using git even for hobby projects lately just for consistency. So, yeah, git doesn't seem nearly as scary to me now as it did when you all were first pestering me about it. :)

In any case, I've finally got the Rage code up on GitHub. And as an added bonus I've put the Quake 3 code up there too for easy access! I'll most likely put any future projects I do up on GitHub as well, just for the benefit of having them all in one place.


Monday, August 1, 2011

The somewhat depressing state of Object.create performance

I have recently been introduced to the niceties of the new EMCA 5 Object model, which revolves around Object.create. The syntax is a bit wonky to those of us that have been javascripting for some time now, but once you get used to it there are some really great features at work here, not the least of which are actual properties, a much better inheritance model, tighter access control, and more! I'm not crazy about losing the ability to "new" my objects, and the funny little hacks that you need to put in place to simulate a constructor are turn-offs for me, but past that there's an awful lot to love here...

... except the performance.

I was curious about how the new model compared with the tried and true methods in terms of speed, so I whipped up a simple jsperf benchmark to gauge how different aspects of the two object methodologies performed. (And I'm not the first either) The results, frankly, were rather depressing.

On my iMac with Chrome 14 (dev channel) new Obj() is currently outperforming Object.create() by a factor of 10! Seriously! 10 times slower, and we've lost constructor functions along the way! Fortunately member access and function calls are virtually indistinguishable performance-wise once the objects are created, which is good (if expected). Sadly, however, utilizing Properties (one of the big bonuses of the new model) is painfully slow. My tests showed a Property to be 200 time slower than a good old setFoo/getFoo pair. The numbers are about the same on Safari, though Firefox showed some interesting variations. There wasn't a single platform where the new model could be called a clear performance winner though.

Of course, the feature is fairly new and hasn't undergone the rigorous optimization that some of the older methods have, so I would fully expect to see these numbers improve moving forward, but for now if you're performance conscious you'd do well to steer clear of Object.create.

(Oh, and despite drastically redesigning the Javascript object model we STILL couldn't be bothered to add operator overloading? Really?!?)