Skip to content

Use hashArray() instead of hash() in RenderObject.getDynamicCacheKey() to avoid unnecessary repeated array allocations #34535

Description

@PoseidonEnergy

Description

In src/nodes/core/NodeUtils.js, hash is defined as a variadic function:

/**
* Computes a hash for the given list of parameters.
*
* @private
* @method
* @param {...number} params - A list of parameters.
* @return {number} The hash.
*/
export const hash = ( ...params ) => cyrb53( params );

Because it's variadic, every time it's called, it allocates an array to hold the arguments in params.

The problem is that this function is called at least once for every Mesh in a scene for each render inside RenderObject.getDynamicCacheKey(), and twice if receiveShadow = true.

For a three.js scene with 1,000 meshes being rendered at 120 frames per second, this results in 120,000 arrays being allocated per second. With receiveShadow = true, that's 240,000 arrays per second, not a small number.

You can see this repeated allocation happening at runtime if you run a performance analysis and look at the call stack:

_renderObjectDirect → get → needsUpdate → getDynamicCacheKey → hash$1 → NewDenseFullyAllocatedArray

The following method should be changed to use a pre-allocated scratch array, and pass that to hashArray() instead of hash() so no temporary arrays are allocated.

/**
* Returns the dynamic cache key which represents a key that is computed per draw command.
*
* @return {number} The cache key.
*/
getDynamicCacheKey() {
let cacheKey = 0;
// `Nodes.getCacheKey()` returns an environment cache key which is not relevant when
// the renderer is inside a shadow pass.
if ( this.material.isShadowPassMaterial !== true ) {
cacheKey = this._nodes.getCacheKey( this.scene, this.lightsNode );
}
if ( this.camera.isArrayCamera ) {
cacheKey = hash( cacheKey, this.camera.cameras.length );
}
if ( this.object.receiveShadow ) {
cacheKey = hash( cacheKey, 1 );
}
cacheKey = hash( cacheKey, this.renderer.contextNode.id, this.renderer.contextNode.version );
return cacheKey;
}

Version

r186

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions