minetest / minetest

Minetest is an open source voxel game-creation platform with easy modding and game creation

Home Page:https://www.minetest.net/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Increase performance of irr::core::array

paradust7 opened this issue · comments

Problem

Emscripten build profiling shows that at least 15% of CPU time is spent in irr::core::array::insert during some periods of stutter. In this particular example, the most time was spent in PartialMeshBuffer::beforeDraw, which does an element-by-element push_back from a std::vector to an irr::core::array.

Screenshot from 2022-04-29 23-18-41

(this chart comes from samples of the call stack over a 7 second period)

There are many optimizations that are not done in irrArray, most importantly, optimizing bulk copies (using e.g. memcpy).

Solutions

Proposed solution:

Modify irr::core::array to use std::vector internally, while keeping the same external interface.

The TAlloc/irrAllocator template parameter appears to never be used, so can be removed. setAllocStrategy is also never used, so can be removed. The only other feature that cannot be replicated is set_pointer, which alters the internal pointers of the array. This is only used in one place (CGUITTFont.cpp), so it should be possible to refactor it manually. All other uses of irr::core::array would remain the same.

Finally, it is now possible to add additional methods to support bulk copying/moving/swaping of data between std::vector and irr::core::array. This will make it possible to have PartialMeshBuffer::beforeDraw do a trivial move, instead of an allocation and copy.

commented

All of the irrlicht containers should be gotten rid of eventually, but replacing their internal implementation with stdlib types sounds like a good first step.

The only other feature that cannot be replicated is set_pointer, which alters the internal pointers of the array. This is only used in one place (CGUITTFont.cpp), so it should be possible to refactor it manually.

That's not so simple unfortunately. CGUITTFont wants to call drawing methods that only take an irr::core::array. But it wants to do this without copying the data, which is std::vector can't support. So the only alternative is to change the API.

I have an implementation of this which seems to be working, but I still need to do a lot of testing and verification. So it is not quite ready for review.

minetest/irrlicht@8f2c0f2

65fe97e

commented
		// std::vector<bool> can't be used here because it doesn't
		// allow taking a bool& reference to individual elements.

If you need that you could use std::vector<u8> instead of writing a custom implementation.
(would require changing the type but that's not a problem)

Making this backwards compatible would be painful. All changes in both repos would have to be behind ifdef.

Because each repo's PR is separate and they both need to be applied to work together, the workflow tests can't test anything except backwards compatibility.