Showing posts with label speed. Show all posts
Showing posts with label speed. Show all posts

Tuesday, 29 June 2010

Fixing the bleedin' obvious

I have quite a lot of computers in my life, and they all run Linux. In fact, the only time I leave the confines of my beloved Linux is when I'm at work (where my machine at Moviestorm Towers is a Macbook Pro). Most of my machines run a variant of Linux called Ubuntu. Last year, the Ubuntu development team announced a new project which they called 100 Papercuts. The idea was that they would identify 100 little irritations which were reasonably trivial to fix. Most of the issues identified were minor and really not too significant, but as they all pile up they start to become a serious problem. One papercut, after all, is only an irritant, but if you get enough papercuts all at once you just might bleed to death.

I was quite taken with this idea (the papercuts concept, not the bleeding to death), and spent some time talking about it with Dave and Andrew. As a consequence, we recently launched our own "papercuts" project for Moviestorm. Whilst Ubuntu's Papercuts project attracted over 1600 recorded bugs within a few weeks, our initial brainstorm generated a slightly less ambitious 200(ish) issues. We're going to be tackling these "papercuts" a few at a time, aiming to fix between 10 and 20 papercuts each time we have a code release.

Let's take a look at some of the papercuts for the forthcoming 1.3.1 release.

MS-3277 Keep window positions and sizes after the user has adjusted them
Wouldn't it be nice if, when you moved a customisation window over to the left, it appeared in the same place when you next reopened it? Now it does. We haven't implemented this behaviour for every window yet, but it's in place for all of the "adjust something" windows (what we call Activity Customizers).

MS-4887 Improve transitions between major mode views
This one's not so easy to spot, but the load time required to switch Views - to move from Set Workshop View to Director's View, for example - has been much improved. A lot of clever process threading and Clever Engineering Hacking in the background has allowed us to make these transitions faster and smoother.

MS-4826 Can't remove user images
I'm going to be totally honest with you here: this is one of those bugs that represents a lack of functionality not through deliberate choice but just because we forgot to put it in. Once you add a custom image to a set object, there's no way of actually removing that image if you change your mind later. The ring menu for such objects now features a "clear image" option, which removes the image. It also works for held props and bodyparts.


MS-4815 File overwrite message is confusing
This one was ridiculously easy to fix, but had still been sat in our bug database for a long time. Being such a small team, it's easy for small things like this to never actually make it onto anybody's "to do list", simply because there are so many other, bigger things that need to be done. That's exactly what the papercuts project is good for: making sure that issues like this do eventually get addressed. Here's the dialog as it appears in the current released version of Moviestorm:
And here's the new version:
A lot clearer, I think you'll agree.

MS- 4809 Can't find the movie I last worked on
My Moviestorm "movies" directory currently holds about a hundred different movies, in various states of completion. When you spend a lot of your working day testing Moviestorm you tend to accrue a lot of test movies. The load screen will now allow you to sort those movies, either by name or by modification date. That means that the movie you last worked on can be quickly brought to the top of the list.

MS-4806 Typo on first page of Help
Yes, well. The less said about this the better. Let's just move on, shall we?

MS-4786 Warn me if I'm not placing a character at time 0
Ever had a character appear halfway through a scene because the timeline wasn't at the start of the scene when you issued the "place here" command? Yeah, me too. Not any more:


MS-3690 Autosave
Matt has already blogged about this one.

There are about half a dozen other papercut issues in various stages of completion, but this should give you some idea of what we're hoping to achieve for 1.3.1. This is an experiment, so the choice of which of our 200 papercut issues to address first has been almost arbitrary. What about you? What little annoying niggle would you like us to fix? Comment with your papercuts, and I'll add them to our issues database.

Thursday, 14 May 2009

Faster, Pussycat! Kill! Kill!

One of the unending background tasks round here is to make Moviestorm run faster. I managed to persuade Julian to take a few minutes out to tell you what he's been doing. If you get bogged down in the techspeak, just skip to the last paragraph. ;)

Recently, I have used the small amounts of time not devoted to watching Russ Meyer films to attempt to make Moviestorm run faster. I don't even want to count the number of changes I've made, but it's quite a number.

One of the things about performance improvement is that not everything you think makes things faster actually does. In a previous job I was reliably informed by a Games Industry "Guru" that "I shouldn't need to profile my code because I should know where the bottlenecks are". Let's leave aside the distinct possibility that this was to avoid him having to buy me a profiler. The real moral of the tale is "what you assume makes an ASS out of U and ME". I'm frequently wrong about such things - most devs I know are, to err is human etc, and in a complex app with threads and the like such as Moviestorm, it is very easy for us mortal non-Gurus to miss the wrong end of the wrong stick.

So my life has involved the use of Java profilers for a 30,000ft view of what's going on, and an OpenGL debugger to see what the individual molecules are up to within our favourite application. First off, I've identified some of the critical code, the 10% that runs 90% of the time. (I say "some of" because Moviestorm is an open system, and adding props and characters with new materials and activities can drastically change the balance of the call state.) Once I know what they are, there are a number of strategies I've employed to speed things up:

* Open GL state management. I've written a GL wrapper that tracks state and rejects redundant changes. Using my magic tools, I've seen that the graphics card on the test machine was hardly breaking a sweat on a scene with 7 characters. Therefore I don't expect to see this optimisation making a big impact YET. I guess it's good news - we can do lots more pretties without hurting the frame rate provided they don't cost a lot of CPU to set up.

* Workspace variables in bottleneck systems. You'll see a lot of maths code using static variables named things like vWork1 to avoid the cost of doing eg

Vector3f pos = new Vector3f();

Yes, the code is less readable, but that's optimisation for ya (in more complex cases I've preserved the semantics so that instead of writing

Vector3f pos = new Vector3f();

I write

Vector3f pos = vWork1;

and hopefully the JIT can optimise, but who knows?)

Why is this inefficient? Firstly, the memory allocation takes time; there are also THREE constructors called when you construct a Vector3f for instance - Vector3f, Tuple3f and Object; plus there is time to zero the x/y/z fields AND there is a hit on the GC side because lots of small short-lived objects can be a nightmare. In frequently-called code, this can accumulate and deferring the calculations to pre-allocated workspace saves these overheads.

As a general point of advice, it's only worth doing this if you know the code is causing a performance problem - ie you've profiled it some way (either using Netbeans' profiler or timing method calls manually). Early optimisation is the root of all evil, remember! (Donald Knuth, Mr Computer Science, circa 197x).

* In-place calculations. In some functions, the results are allocated dynamically (which exacerbates the problems mentioned above). So I've written versions that use pre-allocated arguments, and inlined the relevant code where appropriate.

* Removed redundant field settings in constructors. Eg in Vector3f(), the fields were set to 0 even though Java guarantees to have done this already.

* Caching of invariant state. Many bits of code do searches for things which never change, wasting valuable cycles.

* Lazy evaluation of dynamic state. Some states change at a significantly lower frequency than that which they are polled at. For instance the world transform of a scene object. This gives us an opportunity to only recalculate such state values when we really need to (in the SceneObject's case when its local transform is modified in some way).

* Map iteration. I've changed some iterations over hash maps to use the entry sets rather than the key sets as then the values and keys come for free (as opposed to doing a lookup for the value).

* Many of our skeleton operations are faster now that I've speeded up traversal of bones, and eliminated a number of tests that only need to be performed once.

The first item aside, these are all on the CPU side of things. I'm currently working on some graphics optimisation. I've changed the way our primitives sort and collected them up into batches. Batches require only one setup and teardown, so we win when the batches are bigger than 1 prim, and never lose (the overhead for batch generation being small). It's going well though it has required a big overhaul of the render code.

OK, so far, so much techno-babble. How has this improved speed? Well, on our test machine, we were rendering at 10.6fps on my test scene with 7 characters, lights and quite a few props. After 2 weeks of optimisation, the same scene ran at 32fps. Cool! But the machine is a monster, and it remains a priority to get the speed up on lesser beasts. Optimisation is a war of attrition: lots of small changes can be hardly noticeable; but put one more in, and suddenly things start to flow. Then again, when one bottleneck is removed, another will surely rise to take its place. Slowly slowly catchee pussycat (oh, how I love mixing antonymic metaphors). There are a number of areas we are aware of where we can make yet more speed gains; my notional target is 20-25fps for a moderate scene on an average PC / Mac, and I'm optimistic we can hit this. The only way is Up!


So there you have it. With luck, I'll get Dave to tell you something next week about the work he's been doing on the launcher, which is already giving us much faster load times on our test machines. We've obviously got to do a shedload of testing on the new code before we ship it to you, as there's always a risk that we've broken something major, so we've got this pencilled in for the release after next, assuming all goes well.

Oh, and please don't ask me what any of this means. All I know is Moviestorm runs a lot faster now.