Javascript Style

A lot, most, basically all information on game programming is written using C++. Which is very proud of it's object orientation. Classes were added to Javascript in 2016, so should we use them or their equivilant factory functions in our games? I mean, for clarity it might even make sense to keep teaching OO programming infinitely into the future. Now, if we want to squeeze every extra frame out of our performance the is a clear answer to whether introducing OO to this game engine class is a good thing or a bad thing.

Performance Cost

Is there a performance penalty to using object oriented techniques in Javascript? this guy did some real work to show the performance hit you get from using classes versus javascript's prototypes for making objects and using them.

He found that class inheritance specifically came in 10 times slower than prototypal inheritance.

And just to be sure the JS engines haven't gotten any better since he wrote this code, I tried it myself. This was his empty classes.

Classes vs Protos:
Classes: Min:  0  Max:  3 Med:  0 Mean:  0.4155844155844156
Protos: Min:  0  Max:  3 Med:  0 Mean:  0.3866133866133866

Classes vs Protos (inheritance):
Classes: Min:  1  Max:  3 Med:  1 Mean:  1.2577422577422577
Protos: Min:  0  Max:  2 Med:  0 Mean:  0.38461538461538464

Classes vs Protos (inheritance from build-in object):
Classes: Min:  9  Max:  15 Med:  11 Mean:  10.56043956043956
Protos: Min:  0  Max:  2 Med:  0 Mean:  0.44455544455544455

if we hack it a bit to use the full cornucopia of data types, the numbers go up and show a bit more of a difference.

class X{
  constructor(a, b, c, d, e, f, g) {
    this.a = a;
    this.b = b;
    this.c = c;
    this.d = d;
    this.e = e;
    this.f = f;
    this.g = g;
  }
};
new X(null, 2, 3, 4.0, {a: 1, b: 2}, [1,2], "seven");
Classes vs Protos:
Classes: Min:  3  Max:  11 Med:  8 Mean:  7.516483516483516
Protos: Min:  3  Max:  10 Med:  7 Mean:  7.437562437562438

Classes vs Protos (inheritance):
Classes: Min:  1  Max:  3 Med:  1 Mean:  1.2457542457542456
Protos: Min:  0  Max:  2 Med:  0 Mean:  0.3986013986013986

Classes vs Protos (inheritance from build-in object):
Classes: Min:  9  Max:  11 Med:  10 Mean:  10.134865134865136
Protos: Min:  0  Max:  2 Med:  0 Mean:  0.44955044955044954

And on Chrome the results are worse. Averaging 10ms to create 10,000 new object creation. To put that into perspective, a whole frame in a 60fps game is 16ms. Testing in this way allows us to know, not guess, if something is affecting the performance of our code. This is a good habit to get into and seperates the engineers from the hype-men.

Chrome:

Classes vs Protos:
run.js:28 Classes: Min:  3  Max:  12 Med:  9 Mean:  9.118881118881118
run.js:29 Protos: Min:  2  Max:  12 Med:  9 Mean:  8.91008991008991

run.js:32 Classes vs Protos (inheritance):
run.js:43 Classes: Min:  1  Max:  4 Med:  1 Mean:  1.3756243756243756
run.js:44 Protos: Min:  0  Max:  2 Med:  1 Mean:  0.5204795204795205

run.js:47 Classes vs Protos (inheritance from build-in object):
run.js:58 Classes: Min:  12  Max:  21 Med:  13 Mean:  13.281718281718282
run.js:59 Protos: Min:  0  Max:  2 Med:  0 Mean:  0.4385614385614386

For Loops

In this course we'll also be using a lot of for loops instead of the common convention of using the .map function on an array of data. This is due ot the slow down as well as illustrated in this article. If .map suddently becomes as fast as a for loop, well good for them. Still for loops are worth it, if only to better match with game programming exxamples in other languages and contexts. For loops are used because they are fast and allow the CPU to preload data from memory, as opposed to map or anything calling another funciton, creating another scope in memory and another function on the stack. The small hit becomes big when you want to iterated over lots of points or other things in the game.

Resource https://towardsdatascience.com/javascript-performance-test-for-vs-for-each-vs-map-reduce-filter-find-32c1113f19d7 https://github.com/dg92/Performance-Analysis-JS

In Sum

Seems that perf testing is pretty easy and useful in javascript to sort out whatever legacy misconceptions we might have about what's most performant. There are other, more complex examples of performance wins but this is a good start. We'll return to performance testing throughout the course. To get a sense of our game engine we need to think of it as an engine. When the garbage collector is freeing and allocating memory and the engine starts to rev and spike like here, we know we need to do some engineering to get that memory footprint more stable and leave more time every frame for the actual gameplay.

During this course I might use a style of Javascript you're not used to. I'm not going to put functions and data together and I'm not going to declare variables within the Game Loop. This allows us to bypass much of javascripts memory management slow downs. We'll manage pools ourselves and declare all variables we're ever going to use before the loop, so no new ones are created. This allows for far far less garbage collection.