HTML and CSS Reference
In-Depth Information
Care must be taken to specify offsets and strides correctly, but it should be clear that a small number of objects
can be used to finely control the type and layout of data in memory. See the TypedArray specification at for full details.
The first obvious advantage of TypedArrays over regular Arrays is the potential memory saving. Much game
code only requires 32-bit floating-point numbers, rather than the 64-bit values that JavaScript uses by default. In the
particle example of the previous section, replacing Arrays with Float32Arrays does indeed reduce memory usage of
the data structure by roughly 50%. Further memory savings can be made where lower precision integers can be used
in place of generic JavaScript numbers.
The major JavaScript engines all have an internal concept of ArrayBuffer and ArrayBufferView that allows
them to make important code optimizations. When the engine can correctly predict that an Object is a specific
ArrayBufferView, it can dereference the data directly from memory, bypassing the usual property lookup process.
Furthermore, because the retrieved data is of a known type, in some special cases it may not need to be converted to
the usual 64-bit floating-point representation before operations can be performed.
For example, replacing Array with Float32Array in the code in Listing 4-8 and ensuring that all constants are
stored in Float32Arrays means that most of the simulation can (in the ideal case) be translated by the JIT compiler into
simple memory reads and writes, and primitive operations on 32-bit floating-point numbers. In general, this will be
much faster than the equivalent operations on values of which the compiler cannot predict the type. However, it can
be very difficult to predict how many of these optimizations a given engine will perform. Optimizations at this level
naturally require several conditions to be met, for example the destination of the operation must be known to be of
the correct type to ensure that calculation results are not affected.
The Math.fround function, included in the sixth edition of the ECMAScript specification, provides a way to
explicitly tell the JavaScript engine that a given operation can use 32-bit precision. It is not yet widely supported at
the time this article is published, but is an example of how the programmer can provide optimization hints to the
JavaScript engine.
It should be made clear at this stage that TypedArrays do have some drawbacks. At the time of writing, they
can be much more expensive than Arrays to create, and the JIT compilers still do not take advantage of all possible
optimizations. In some cases, Arrays can actually result in faster execution, particularly where temporary Objects
are created and destroyed frequently (although in general it is advisable to minimize the number of transient objects
required by a given algorithm).
In our simple particle system in Listing 4-tk, we saw a speed increase of about 10% on some browsers when
all variables use Float32Arrays; however, we saw a slight speed decrease on other browsers compared to the flat
JavaScript Array.
Complex Structures as Single ArrayBufferViews
In the Turbulenz engine, we have written and tested several implementations of a Math library to operate on Matrix,
Vector, and Quaternion Objects, including a set of native implemented functions. At the time of writing, we have
settled on a solution where all objects (Vector3, Vector4, Matrix33, Matrix34, ....) are single Float32Array objects of the
appropriate size.
To avoid creation of temporary objects, all math operations optionally take a destination argument, which allows
temporary or scratch variables to be reused to avoid too much Object creation and destruction.
In some cases, such as our 3D animation library, or 2D and 3D physics engine, structures, or arrays containing
several math primitives are implemented as single Float32Arrays containing, say, a sequence of Quaternion objects
representing animation bones.
In other situations, Float32Arrays can be used to represent structures that include non-float data, so properties
such as flags or indices, which might otherwise be stored as integers, are also kept in a single Float32Array along
with numerical data. It is important to be aware of the trade-off that has been made with code clarity here, but for
key areas that can very easily become an execution bottleneck, we are giving the JavaScript engines the best possible
opportunity to save memory and optimize JIT-generated code.
Search WWH ::

Custom Search