The architecture of the Construct 3 runtime

16
Official Construct Post
Ashley's avatar
Ashley
  • 23 Mar, 2018
  • 1,469 words
  • ~6-10 mins
  • 5,531 visits
  • 4 favourites

The new runtime has been completely rearchitectured. It's forwards-looking to the next years of the web platform. Here are some of the ways it's fundamentally different to the old runtime.

Targeting modern browsers

The modern web platform has changed completely since we started. For example back in 2011 WebGL was very new and experimental, and only a fraction of devices supported it. Consequently we diligently maintained two renderers: WebGL, and canvas2d as a fallback (which at the time most devices used). Now, according to webglstats.com, WebGL is effectively ubiquitous covering 98% of devices. So in the Construct 3 runtime we've dropped support for canvas2d. Being WebGL-only significantly reduces the maintenance burden for working on graphics code, and unlocks a new level of powerful graphics features. This is how the new runtime brings back a built-in color tint feature for most objects, as Construct Classic originally had: it can be done very efficiently in WebGL, but not in canvas2d. Without having to worry about the fallback, we can storm ahead with exciting new features. We also plan on bringing back other advanced rendering features like mesh distortion.

Similarly, we've ditched three (!) other audio APIs in favour of the now ubiquitous Web Audio API. This considerably simplifies our code and allows for the most powerful features to work everywhere. We also freed ourselves of a ton of old compatibility cruft, such as bug fixes and workarounds aimed at browsers as old as IE9, as well as long-defunct platforms like directCanvas. Overall our codebase is now much more concise and a lot easier to work with.

Sharing code with the editor

Conveniently, both the editor and runtime are now written in JavaScript. This allows us to share significant components between both. A great example is our new WebGL renderer, which we wrote about last year. It's redesigned to fully support WebGL 2 features throughout, with fallback to WebGL 1. We've been able to directly use the identical code for the new improved renderer in the new runtime. Any additions or optimisations we make to it automatically improve the editor and runtime simultaneously. This also helps guarantee that the editor displays identical results to the runtime.

Similarly there is a great deal of general library code that we share between the two, making it quicker and easier to code. Some further places we share code include the new styled text layout engine, particles engine, and shadow casting engine. These are used for previews in the editor and since the code is identical, it provides a great guarantee that what you see really is what you'll get, as well as eliminating the need to maintain two copies of each.

Combined with targeting the modern web platform, sharing code allows us to be much more productive when writing code, with far fewer worries about compatibility and maintenance. It also provides a better in-editor experience as you can see things like formatted text right in the Layout View without having to start a preview.

Improved code quality

The quality of the code we work with doesn't always directly affect users. However it is key to ensuring we can work quickly when adding features, optimising, and fixing issues that come up. Overall this allows us to get more done for our users.

The new runtime has been completely rewritten with an entirely new style, honed over time and proven to be flexible and robust during the development of the Construct 3 editor. The new runtime is far better organised with a much more sensible arrangement of code, making it a lot easier to adapt over time.

The use of modern JavaScript syntax also helps enormously to make sure it's clear what code does. It's genuinely like a whole new language, and it's liberating. Additionally new data structures available in the latest versions of JavaScript, combined with improved algorithms, are responsible for many of the performance improvements we highlighted previously.

Overall we are confident we have a much stronger foundation upon which we can build new features for the next years to come.

Hosting in a Web Worker

We saved the best for last. By far the biggest overall change is the fact that the Construct 3 runtime is now capable of running in a Web Worker, independent of the main thread. It's still an experimental feature as browsers haven't even finished launching the necessary features, but we have it working already. It takes a little explaining to understand why this is important.

The old runtime - and most other existing web-based engines - are essentially locked to the same CPU core as the browser. It uses the same execution thread as the browser itself does for many tasks, known as the main thread. This means if the browser does some work - or even an iframe or background tab, in some cases - it can interrupt the main thread and prevent the runtime from doing work. This is one of the causes of jank (small pauses that interrupt the smoothness of the game). Some browsers even run preview in the same thread as the editor, so the editor can jank preview and vice versa. The following image illustrates how execution can look over time.

The aim is to demonstrate that the runtime has to contend with lots of other bits of work done by the browser or possibly other frames or pages. To their credit, modern browsers are pretty good at slicing up work to small chunks and running code in other threads to try to avoid causing jank. However it's not always possible, and some things like styling and layout simply have to be done on the main thread. In short, the main thread can be a busy place.

Web Workers are a way to run JavaScript in a new thread of its own. This prevents anything else happening on the main thread from holding up execution in the worker: it continues to run in parallel. The operating system can even schedule it on a different CPU core. Once the runtime is hosted in a worker, it can continue regardless of what happens on the main thread, looking something like this:

This allows slightly more time to run overall, but more importantly, it runs uninterrupted - nothing the browser or other pages does can jank the runtime. It effectively removes the overhead of the browser: nothing the browser does has a performance impact on the runtime any more.

The downside though is that Web Workers have a very limited set of capabilities. For example they can't directly receive input events, create elements in the page, or use some APIs like Web Audio. As of recently they couldn't even render to a canvas, but thanks to the latest web platform features this is now possible, and is largely responsible for making it feasible to move to a Web Worker. To work around the missing features we created a bridge to efficiently communicate between the runtime and the main thread to access any additional features it needs. Our measurements show this has no significant impact to input latency. Further, even if heavy work needs to be done on the main thread, the runtime still continues in parallel. If it needs a result, it will simply receive it later on.

For the vast majority of cases this works great; however there are a few corner cases where we'll need to adjust features to not expect a result immediately. We might need to make some changes accordingly, but we think it'll be well worth it. The end result is a dedicated thread just for the runtime, guaranteed to be free from any browser overhead.

Conclusion

Construct 2 was one of the first HTML5 engines on the market, and amongst the first to adopt WebGL and Web Audio. In keeping with our strategy of developing on the bleeding edge of web technology, we are again one of the first engines to make the jump to running entirely in a Web Worker. It is a significant technical feat to accomplish this with a full-featured engine and involved the kind of fundamental architecting that is difficult to retro-fit to existing engines. With this we believe we will remain at the forefront of web gaming technology, providing the best and most optimal platform for all your games to run on. Combined with all the code improvements and modern browser technology, and all the other improvements we've detailed previously, the Construct 3 runtime is a huge technology upgrade. It's the next big step in the development of Construct, and we can't wait to see where we go from here!

Catch-up

Missed a previous post? Here's the blog series so far:

  1. Announcing the Construct 3 runtime
  2. New text features in the Construct 3 runtime
  3. Behavior improvements in the Construct 3 runtime

Subscribe

Get emailed when there are new posts!

  • 1 Comments

  • Order by
Want to leave a comment? Login or Register an account!