Closed elunty closed 6 years ago
It certainly triggers something, judging by the performance graph. The same results with a current Firefox, btw.
Default:
After switching to string (note all the orange boxes, it's always garbage collection ~1MB in size)
https://github.com/mrdoob/three.js/pull/12960 I have a simple solution up to force parse into float.
But why would a vector3 that has nothing to do the actual logic of the example destroy all performance? Very strange.
It will need investigation, but it may have to do with the number of calculations performed by ray tracing on a vector and a potential casting of the string into a float many times.
But we don't pass that vector in the raycaster at all. It's on its own doing nothing
Passing in a string value converted Vector3-related code to be polymorphic rather than monomorphic:
https://github.com/davidmarkclements/v8-perf#polymorphic-vs-monomorphic-code
V8 and modern JS engines in general have something called hidden classes, which allow for optimizations as if JS were statically-typed.
For example, if you had this code (does nothing in particular):
const vector = new THREE.Vector3(1, 2, 3);
vector.x += 5;
vector.multiplyScalar(2);
const matrix = new THREE.Matrix4();
vector.applyMatrix4(matrix);
Then Chrome/V8 can reasonably assume that all of the Vector3 values are numeric and can execute the code as if this was the case:
class Vector3 {
x: number;
y: number;
z: number;
}
When you set a property of a Vector3 instance to a string, V8 creates a new hidden class, and the existing optimizations are weakened:
class Vector3WithXAsAString {
x: string;
y: number;
z: number;
}
The code-paths are updated to handle this class. Simplified, V8 ends up having to do something like this for method calls, property accesses, etc.:
if (vector is Vector3) {
// use optimized version
} else if (vector3 is Vector3WithXAsAString) {
// use slow version
}
@razh - your second link comes with the heading:
"Disclaimer: A lot of the information on this page is not accurate anymore."
Nonetheless, this is a very interesting point and certainly looks like a reasonable explanation.
Yeah very interesting.. wasn't aware optimization like that occurs behind the scenes.
Closing, since this is not an issue in the library. User have to ensure correct parameterization and type usage in their code.
Description of the problem
So I'm not sure what to even call this... I guess an oddity more than anything. I noticed this on a site i have when my raycasting was way slower than i had expected in certain scenarios. Here is the easiest way to reproduce:
I just don't understand what the heck is going on. Was it my fault for creating a vector 3 with a string? Probably. But i just don't get how doing something like this grenades the performance of the entire scene. Maybe you could force a parseFloat on vector data?
Im not sure if this bug makes all threejs actions slower or just raycasting, but that is where i noticed it the most.
Extra notes: Doing the same thing with vector2/vector4 does nothing.
Three.js version
Browser
OS