Open sebcrozet opened 4 years ago
See the new-api branch for an overview of the ongoing changes.
Suggestion: To reduce GC pressure and let you delete some code, instead of creating new objects in https://github.com/dimforge/rapier.js/blob/master/src/dynamics/rigid_body.rs#L9 and https://github.com/dimforge/rapier.js/blob/master/src.ts/dynamics/rigid_body.ts#L57-L58, create a Float64Array
or Float32Array
inside the WASM memory for each new RigidBody
's position
, rotation
and then update that in Rust directly. For any other temporary Vector-like objects, you could have a few extra Float64Array
's preallocated that you pass it a byteOffset to write to, so you don't have to create new objects.
You can allocate these arrays in the WASM memory directly, which means Rust can update it without a JS<>WASM API call and without creating new objects on each of those calls.
From there, you can keep the same interface for the JS Vector objects by overriding getters/setters:
class Vector3 {
array: Float64Array;
get x() {
return this.array[0];
}
set x(v: number) {
this.array[0] = v;
}
get y() {
return this.array[1];
}
set y(v: number) {
this.array[1] = v;
}
get z() {
return this.array[2];
}
set z(v: number) {
this.array[2] = v;
}
}
This will make Rapier's JS bindings faster because, as far as I can tell, Rapier.js creates a new JavaScript object every time you want to get the translation()
of a RigidBody
which will likely cause garbage collection freezes.
Problems with the current bindings
The current JS bindings need to be reworked to address the following problems:
rigidBody.linvel()
will return aVector
which has to be explicitly freed by the end-user withvector.free()
. This is very bad because it is very easy to forget to free something, which will ultimately lead to leaks.World
structure which is convenient but will become quite limited in the future once rapier exposes more pipelines than the physics pipeline.New design
In order to address these problems, we should modify our bindings by splitting them into two elements:
RigidBodySet
,ColliderSet
,PhysicsPipeline
, etc. but not the colliders and rigidbodies for example. This will solve the manual-memory management mentioned in 1 because it will automatically free transient objects that could have been easily forgotten by the end-user.Another bonus of the high-level bindings is that they will allow us to design a more JS-idomatic API by defining, e.g., builder patterns.
About backward compatibility
This change will necessarily be a breaking change. However we should attempt to limit as much as possible the amount of breaking changes. To do so we will:
World
structure in the high-level bindings. This structure will work like the current monolithicWorld
so that existing code wont suffer too much from this binding rewrite. At some point in the future we may end up makingWorld
as deprecated.0.2.0
to show that a breaking change happened.