Performance
rfw
chooses certain abstractions, conventions, and trade-offs that can allow for great performance. It also provides some tools for the user to do the same - if they so choose.
Check out the benchmarks that some of these decisions are based on.
for
-loop iteration is a lot faster than iterator-based iteration (for ... of
) or methods likeforEach
.For arrays: Iterate arrays with a simple
for
-loop.tsconst a = [1, 2, 3]; for (let i = 0; i < a.length; i++) { const e = a[i]!; }
For
Set
andMap
: Possibly userfw
sArraySet
orArrayMap
(or evenSparseSet
). These trade memory (they keep both aMap
and an array) for iteration speed (because the array can be iterated with afor
-loop).tsconst am = new ArrayMap([1, 2, 3]); // `ArrayMap.size` (and `ArraySet.size`) are getters, if iterated _very_ often it's better to save the function call const size = am.size; for (let i = 0; i < size; i++) { const e = am.values[i]!; }
Disregard array order on mutations if not necessary.
Especially
Array.splice
to remove elements from arrays is very inefficient. If the order of the array is irrelevant, consider doing a swap-delete.tsconst a = [1, 2, 3, 4]; // Has to move everything after index 1 and allocate an array for the return value a.splice(1, 1); // a is [1, 3, 4] here // Swaps 3 with 4, then truncates swapDeleteAt(a, 1); // Or swapDelete(a, 3) where 3 is the searched for value
See
swapDelete
,swapDeleteAt
.Use object pools.
When many short-lived objects of a kind are needed an object pool might come in useful.
tsconst vecPool = new Pool<Vec2>({ create: () => Vec2.zero(), reset: v => v.set(0, 0), }); const v1 = vecPool.take(); const v2 = vecPool.take(); vecPool.return(v1);
See
Pool
.