Hi all,
I ran a benchmark across various 2D engines to check rendering/processing performance - no Unity or Unreal sorry. If you're familiar with the bunnymark benchmark, it's similar - spawn a lot of instances, give them each a random direction/velocity, and wrap their positions to the screen. The result shown is the number of instances the engines could handle before FPS dropped below 30FPS. Tested on Windows 10 PC with Ryzen 3600, 16GM RAM, Radeon RX 570. Construct 3 was tested with Edge (Chromium) but the other engines were all exported to native applications.
Gamemaker Studio 2
Gamemaker has several export options - VM (C++ engine but running interpreted GML code) and YYC (everything is compiled into c++) - and for both of these there's a 32-bit option and a new 64-bit option. Results:
VM 32-bit: 37,000
YYC 32-bit: 39,00
VM 64-bit: 48,000
YYC 64-bit: 67,000
YYC 64-bit Delta Time*: 55,000
*Note that by default GameMaker used fixed step timing (no delta time), so to make a fairer comparison I ran another test incorporating delta time.
AppGameKit Studio
AppGameKit Tier 1 uses a C++ engine to interpret AGK script - this seems to be the option used by most developers. There is AppGameKit Tier 2 which is basically using their API to help write the game in C++ but I didn't test this. Results:
AGK Tier 1*: 21,000 - 36,000
*Note the range of values - it dropped to 30FPS at 21,000 but was able to hold 30FPS up to 36,000 - I suspect this is related to how they handle frame timing or report FPS.
GDevelop
The only other JavaScript based engine on the list. Was curious given it's 'similarity' to Construct. Results:
G-Develop: 15,000
Godot
Godot uses a C++ engine to interpret GDScript - again this seems to be the option used by most developers. There is the option to write in C# or C++ (with a lower level API) but I didn't test this.
Godot GDScript* - 21,000
*Note that this was a debug build because I had issues trying to compile a release build, so performance is lower than it should be, but based on past experience it is slower than GameMaker VM, so my guess would be 25-35,000 in a release build.
Defold
Defold uses a C++ engine with LuaJIT scripting (generally considered the fastest interpreted language). Results:
Defold*: 16,000-25,000
*Note this another case where the engine drops to but then holds to 30FPS.
Raylib
Raylib is a pure C engine, very light weight and very low level, more framework than engine, similar to SDL, SFML etc. Also worth noting that this benchmark was programmed somewhat differently, it doesn't use instances, but a large array of positions, velocities etc., and then uses those array values to draw the texture - it is very performant in terms of memory access/CPU caching etc. - it would be more similar to how Construct 3 handles particles VS sprites.
Results:
Raylib: 230,000
Raylib with rotation*: 150,000
*Note that there are different rendering commands depending if the sprite is rotated. As you can see having to apply a rotation transform has a significant performance impact.
NOW WHAT YOU HAVE BEEN WAITING FOR!
Construct 3
The Construct 3 benchmark was programmed in multiples ways; (a) using the inbuilt bullet and wrap behaviours (b) using events instead of behaviours (c) using a conditional expression instead of multiple IF events. Results:
C3 behaviours: 72,000
C3 events: 60,000
C3 conditional expression*: 85,000
C3 conditional expression with rotation*: 58,000
*Construct 3 seems to have an optimization which allows it to render non-rotated sprites more efficiently.
Final Thoughts
Hats off to the Construct team. These results had me triple checking my Construct code to make sure I wasn't cheating.
Apart from Raylib, which was expected to easily win and isn't really a fair comparison, Construct 3 shows better performance than the other engines. Construct even manages to beat the fully compiled C++ native export of GameMaker, which was really surprising actually.
There is some overhead to events (about 20% in this case), however I feel like I could have optimized the events version a lot more if ELSE conditions in Construct worked like in other languages, i.e. filter a smaller and smaller subset of instances to subsequent conditions.
The fact there seem to be inbuilt optimizations for rendering non-rotated sprites etc. is nice. And the boon is that Construct performance was better while at the same time offering more inbuilt functionality than most of these engines.
Not to end on a downer, but keep in mind benchmarks are benchmarks, and don't reflect a whole game. I know there are certain things like tilemaps and collisions which are faster in other engines. But on the whole, a very impressive showing by Construct.