Home Artists Posts Import Register

Content

So in an attempt to keep things from dragging on too long, I didn't go into a ton of detail on what asynchronous processing means for AW and twine games in general, and i left out a pretty important aspect of how it improves performance overall. It's not a simple topic, but I think that I can explain it in a way that will (hopefully!) make sense for everyone.

That said, there be technical talk ahead arg. (it's after 1am, I'm tired.)

The first issue to bring up is the limitation of JavaScript and other scripting languages in general (and games that utilize scripting language, such as in Inform7, and many others). There is a limit to how fast code is executed. (For ease-of-speaking, we're going to call this a thread rather than a more appropriate technical term. This isn't the same as a processor thread. Just think of it as a string of instructions being performed.)

The major limitation (and advantage) of a scripting language is that it isn't compiled into machine code. Instead it is executed by another program, in this case your browser, which has to interpret the script and turn it into machine code to run. This makes things slower, but for the scale we're talking about with our games, it's not a huge factor.

JavaScript and the engines that run it are far more advanced than many of the custom programs out there that run script code (again, such as Inform7). In fact, JavaScript has gotten so good, it's slowly replacing PHP server-side as well. So why do threads execute so slowly? because of throttling. Imagine your browsing experience if websites chaotically used your system resources, and ended up competing with each other and the browser itself to execute. It'd be pretty crazy, and nobody would be happy. This is why, with certain games like FC, increasing the power of your computer doesn't have the expected result on speed. The slower computer is already "fast enough". The increase in power only causes a minor change to that throttle.

There are two ways to get around this. 1) create an executable out of your javascript, and tweak the compiled JS engine not to limit thread processing speed. 2) use asynchronous programming.

Major commercial websites handle this with asynchronous programming, and aside from the markedly increased complexity (partly due to adding in the game aspect), there's no reason we can't either!

So, now that we know the route of the problem, we can look at how async can work as a solution. The first way (and in the way I explained it in the previous post, the most simplistic), is to split the game into two threads, one doing the processing of NPCs and such, and the other lets the player continue on with some aspect of the game. This is great by itself, and would already be an improvement over simply staring at a blank screen or even a loading screen, while waiting for a page to populate.

While that game-design aspect is nice, async can also rapidly speed up the overall processing time. This is because you can split a thread into numerous threads. Let's say there's a basic process of checking an NPC with about 250-300 variables for all the effects that happen over the week. Each NPC takes say 3 seconds to complete. Now let's say you have 5 of them. That's 15 seconds in a for loop to get through all of them. When your NPCs grow to 20, you're looking at a full minute wait. It seems insane to imagine a game (like AW) that's going to be doing this for considerably more. 

If we used async, however, we'd use that same for loop to start asynchronous functions (basically copies of the same function) all running individually to process the NPC that is assigned to it. The main synchronous function awaits promises from the async functions to be filled, and continues afterward. (this is very simplified.) It still takes 3 seconds to process a slave, but let's be pessimistic and say the process of setting up and collecting the async functions adds an extra 3 seconds. How long does it take to process 20 NPCs? 6 seconds. That's ten times faster. but the speed gain is more impressive with larger numbers. If AW has 100 NPCs to process, those NPCs might take 5 minutes of staring at a screen without async. That's certainly too long for a week summary and planning session. Instead, we just run 5 batches of 20 in 20 seconds. (using batches because we don't want to cause slowdown on slower devices.)

Async can even be used to speed up displaying things. Let's say you're showing a contacts list with all the main information from all the NPCs your player character knows. You want it to look fancy, so you do some logic to output different colors to different text. It isn't a lot, but it still results in the page taking a few seconds to load a display of 10 NPCs. 

Instead, you set up the page with a forwarder passage or use a DOM macro. prior to loading the page, you split checking each NPC to an async function, and output the results to a variable as a html string. Then you forward to the intended passage, or use DOM to replace current page contents. Your print your strings, which takes next to no time at all, making the whole process much quicker.

And now, it's super late, and I'm super tired, so I will hopefully super sleep. Goodnight!

Files

Comments

Tat Beard Dude

Great info, and easily relatable. You should probably also teach/tutor this with your level of comprehension and ease of breaking it down. But at this point that may be a step backward on the ladder. You're doing a great job of splicing code to make it work for your ideas. But it looks like there's a kink in the code that gets a lot of people excited for some reason... 😉