Thursday, December 24, 2009

Slower Languages for Faster Code

This post is both an update on performance improvements in the engine, and a general comment about how slower languages can lead to faster code, in a somewhat ironic way.

So, the next game (codename 'swarm') has really pushed the Intensity Engine to new limits: the map is huge, both in terms of raw size (4096 cube units on each side, so imagine something like 500x500x500 meters), geometry (the compressed binary octree is 1.1MB), entities (about 1,000 of them), and includes several new gameplay elements (new bot types, new plot triggers and items, etc.).

So, it initially ran very slowly, which was not really surprising. At first glance, this could lead someone to speculate that the engine, with its approach of doing as much as possible in a script language - JavaScript on Google V8 - simply isn't a good idea. After all, Cube 2, the engine we are a mod of, is written entirely in C++ (well, with cubescript in a very, very minor role), and therefore our engine should be much slower than where we started from. So didn't we just make things slower, needlessly?

First of all, that isn't an apples-to-apples comparison, simply because Cube 2 can't run the new gameplay elements that we have. But more importantly to the current topic, if you did mod Cube 2 to run the new gameplay elements, it would almost certainly run this map more slowly. That seems strange at first, but it really isn't. The reason is that, while code-for-code JavaScript is slower than C++ (even with the best JavaScript engines like V8), using JavaScript lets you implement optimizations that don't make sense in C++.

For example, if you have a fixed engine written in C++, you can of course tune it quite a lot, but there are additional things you can do if each map/game/level can customize things through scripts. For example, the swarm map has a lot of mapmodels, and the profiling tool reported that they were in fact a significant factor in slowing down the frame rate. Since the code that renders them is a script, I was able to easily customize it to run faster, by applying some heuristics that work well in this map (like certain ways of deciding when not to render a mapmodel). Those tricks might not work well in other maps, but that is exactly the beauty of a secure scripting language - each map can have its own scripts, downloaded on demand with the map. Also, I customized how physics for collision checks and so forth is done, and various other things.

Basically, you don't want to download a whole new engine for each map. But that is what modding the C++ code would require. With a script language, on the other hand, you can code a lot of optimizations and distribute them with the map, in an easy way. So you end up being able to optimize a lot more.

(There is another factor here, of lesser importance, but also worth mentioning: It is also simply easier to write those optimizations in a script language than C++, because script languages are faster to code with.)

Of course, C++ has its place - the core engine has to be written in C++. Even Java or C# wouldn't be possible, because while being slower by a factor of 2 is fine for 95% of applications, that is not the case with game engines. Half the frame rate is not acceptable! But on top of a 'core' C++ engine, I believe it really makes sense to integrate a script language, as we do, and not just because it lets you run more types of games, but also for performance.

Anyhow, to get back to the swarm game, at this point performance is good: On my not-powerful-at-all machine I get 60fps in the slower areas, dropping perhaps to 50fps with a lot of action. But in most of the map the frame rate is actually much higher. So, the optimization phase is almost over. What is left is to write the scripts for the final boss battle, and then to do a lot of playtesting and tweaking of the gameplay.

1 comment:

  1. Interesting,

    Have you compared your solution to the one of Adobe Flash Alchemy?

    ReplyDelete