rdkcentral / Lightning

Lightning - The WPE UI Framework for developing Apps and UX
Apache License 2.0
191 stars 109 forks source link

Unnecessary allocations per frame #494

Open itsjamie opened 1 year ago

itsjamie commented 1 year ago

Doing some memory allocations timeline testing in Chrome has revealed a few spots where Lightning is performing a lot of heap allocations unnecessarily leading to a lot of garbage being generated per frame.

The Rounded Rectangle Shader is a key part where this occurs.

Each uniform is set using the variadic function _setUniform and the values are passed as individual parameters, but then put into an array to be passed to uniform4fv, etc. The issue with that, is putting those values into an array allocates an array of those floats. So in our application that leads to ~300kb/s of GC pressure.

Providing the ability to disable the WebGLStateManager and refactoring the uniforms to directly use functions like uniform4f when the parameters are not already in a vector leads to far less GC pressure, and in our experience can drastically improve performance.

Understanding that it may be a design of tradeoffs, wanted to open an issue for discussion here to see if there was anything we could be missing.

itsjamie commented 1 year ago

In addition, to the allocations from the use of setUniform, a shader like RoundedRectangle allocate on every frame in the map function converting the radius to the final int32's.

elsassph commented 5 months ago

Ugh that's bad. For some shaders the arrays could potentially be "cached"?

itsjamie commented 5 months ago

For some shaders the arrays can definitely be cached, but in a lot of cases they can also be entirely avoided if you add the exact functions you wanted to call rather than going through the API of setUniform that only allows a single value parameter

https://github.com/rdkcentral/Lightning/blob/master/src/renderer/webgl/shaders/RoundedRectangleShader.mjs#L145-L151 Those Float32Arrays are only necessary because of the setUniform API of currying the GL function to use only supports a single value for the glFunction.

If instead you had a setUniform[2,3,4]f, you could avoid all that heap allocation and just stack alloc making GC pressure a lot lower.

This largely doesn't matter until you have something animating on screen and then every rounded rect allocs 6 floats of garbage per frame.