skip to Main Content

I have to fill an array with a lot of objects. My current Implementation is this:

let useVertices = [];
const len = this.indices.length;
for(let i = 0; i < len; i++){
    let index = this.indices[i]*3;
    useVertices.push(new THREE.Vector3(
        this.vertices[index],
        this.vertices[index+1], 
        this.vertices[index+2])
    );
}

this.indices is an Int32Array with a length of almost 4 million.
this.verticesis a Float32Array with a length of about 650,000.

The implementation shown above takes between 500 and 800 ms.

The Browser I am using is CefSharp, because the website is run in a C# application.

Is it possible to increase the speed of this code?

2

Answers


  1. Gathering together what I think are the best suggestions from the comments (other than frame challenges) pending your testing them:

    • Ouroborus pointed out that since you have 4M indices but only 650k vertices, you’ll often be creating equivalent THREE.Vector3 instances. We can reuse instances instead, remembering previous ones based on index.
    • Gabriele Petrioli pointed out that you can use assignment rather than push, saving a method call: useVertices[i] = ___
    • You can pre-allocate the array using new Array(len)
    • Avoid unnecessary property lookups by caching indices, vertices, and THREE.Vector3
    • Use const for useVertices if you can
    const { indices, vertices } = this;
    const V = THREE.Vector3;
    const len = indices.length;
    const useVertices = new Array(len);
    const vectors = new Map(); // For reusing vectors
    for (let i = 0; i < len; i++) {
        let index = indices[i] * 3;
        let vector = vectors.get(index);
        if (!vector) {
            vector = new V(
                vertices[index],
                vertices[index + 1],
                vertices[index + 2]
            );
            vectors.set(index, vector);
        }
        useVertices[i] = vector;
    }
    

    (Note: Plat00n tried using an array instead of a Map above, but even with the get and set method calls, the Map was faster.)

    Login or Signup to reply.
  2. You can use – Vectorized approach

    • Use typed arrays (Float32Array) directly for useVertices instead of pushing elements individually.

    • Use vectorized operations like slice and copy to manipulate these typed arrays instead of looping through individual elements.

    • Leverage vectorized functions provided by Three.js like Vector3.fromArray to directly convert from the vertices array to useVertices.

       // Allocate typed array directly
       const useVertices = new Float32Array(this.indices.length * 3);
      
       // Loop through indices and copy data
       for (let i = 0, j = 0; i < this.indices.length; i++, j += 3) {
         const index = this.indices[i] * 3;
         useVertices.copyWithin(j, this.vertices, index, index + 3);
       }
      
       // Alternatively, use Vector3.fromArray  
       const useVertices = THREE.Vector3.fromArray(this.vertices, 
       this.indices);
      
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search