- In C++, member access is a compile time memory offset, it's free.
- If the member you're accessing is large like
Array<vec3>, cache the result in a local variable.
- When possible, iterate using new
for..ofsyntax instead of old style
C++ Member Access
In C++ classes are used as containers to store multiple values in a single place. For example consider the following class:
In memory this is stored using a single allocation that is big enough to fit both floats. When code accesses one of the members, the compiler will statically emit code that knows the exact offset into the data structure.
C++ can also nest structures and arrays inside other structures and arrays. Consider the following:
We can create an instance of
Triangle and a single allocation will be made that holds all 6 floats in linear memory space.
So if we wanted to loop over the vertices printing each pair, it could look something like this:
Again, the complex lookup expressions like
triangle.vertices[i].x are compiled away to a single static offset added to the pointer address. The
triangle.vertices.size() expression in the for loop header is a constant value.
C++ Member Access From JS
lumin module in MagicScript. The syntax can look nearly identical, but the performance cost of lookups is different.
Suppose we have a native function exposed to JS that gives us a triangle:
In the API docs for the bindings,
Triangle.vertices is a member of type
We can loop over this using similar syntax as C++:
triangle is a wrapped native object and
a dynamic call to C++ which returns a fresh array of points every time, the
performance is different!
Cache Expensive Member Accesses
It would be better to cache the result of
local variable so it's only called once and then iterate over that native
syntax that we can use. This new syntax is clearer and performs better since the
triangle.vertices for us.
Real World Use Case
A real world use case of this would be iterating over the
WorldPlaneCastResult to draw the planes as line nodes.
In the docs, it states that
lumin.WorldPlaneCastResult.Plane has a member
.vertices with type
Array<vec3>. We could iterate over this the same as is done in the official C++ example, but it will perform poorly.
In testing there were typically about 13 planes with many vertices each totaling over 1000 vertices.
With this direct port from the C++ syntax, it was taking over 5000ms to render a single animation frame!
planeData.vertices the C++
side and create nested arrays of 3 float values for each point.
This is especially wasteful in the case of the for loop head where we're creating thousands of arrays just to lookup the length of the array.
Refactoring to use
for..in syntax fixes the performance issues and the code looks better.