Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce realloc() count in 4.2 beta #2325

Closed
wants to merge 2 commits into from

Conversation

DimonSE
Copy link
Contributor

@DimonSE DimonSE commented Jul 27, 2023

Hello.

I have several improves for the function spSkeletonBinary_readSkeletonData() which should improve the allocation for spSkeletonData* struct data as a whole.

In our games, we actively use spine graphics in all aspects, including UI, core gameplay, and even in metagame maps. At some point, we found that the default allocator (malloc/realloc/free) wasn't fitting our needs very well.

In a special test project (a clone of a real game), I logged the allocation of 211.18Mb in RAM in total after the game loaded for all spSkeletonData structures, and this is about 2 million+ allocates, mostly 16-32 or 64 bytes each. Clearly, we need our own game allocator in such a situation :)

I worked on the custom allocator, which is a regular linear allocator that simply allocates a large block of memory at the beginning and then moves its internal pointer, giving spine lib the requested bytes bit by bit.

For such an allocator, it was critical not to receive frequent realloc or free, so I also decided to study the possible call sites of REALLOC in spSkeletonBinary_readSkeletonData() and potential improvements.

So, in this patch, I tried to improve the situation, slightly modifying the spine runtime code, this does not lead to any major modifications, or problems, it just significantly reduces the amount of REALLOC.

Here are the improvements:

  1. In spAnimation_create(), I calculate exactly how many timelineIds I need in the totalCount variable. Up to 1/3 of all reallocs were here, I also checked the performance it turns out that to calculate 1 additional for() is much faster on average than several realloc calls (for our spine objects, the typical totalCount value was about 600-1k bytes). Thus, by calculating exactly how much is needed, you can avoid realloc here at all.

  2. In the SkeletonBinary.c _readVertices() function, you can just allocate weights and bones of the right size right away, we already have all the information for this. Maybe there used to be some other code here that was removed, and now all the logic can be greatly simplified, while also removing reallocs.

  3. Also directly in spSkeletonBinary_readSkeletonData() there are several /* TODO Avoid copying of name */ for bone, slots, and constraints. However, the refinement requires modification of spBoneData_create, spSlotData_create etc. Where now no MALLOC_STR is done, but simply taking the string through CONST_CAST.
    Well, of course, this requires also to fix SkeletonJson.c where now MALLOC_STR is done.
    That is, before there were: 2 copies of names for SkeletonBinary and 1 copy if SkeletonJson, and now 1 copy in SkeletonBinary and also 1 copy in SkeletonJson. This doesn't give much gain in terms of extra malloc/free but still good, and trivial to fix /TODOs/

After a series of tests, I found that previously about 12.42% of the memory allocated by the linear allocator was lost due to realloc work in a new place (not so much actually, I thought there would be more), now with such improvements the figure became only 4.61%

I hope you will find such improvements interesting.

Best regards,
Dmitriy Sechin | Programmer in G5 Games

DimonSE added 2 commits July 25, 2023 19:26
…near allocation memory now, also remove unnecessary coping strings in SkeletonBinary
@DimonSE DimonSE changed the title 4.2 beta Reduce realloc() count in 4.2 beta Jul 31, 2023
@badlogic
Copy link
Collaborator

Thanks! I left some review notes. The gist:

  • We can't change the behaviour of the xxx_create() functions to not copy the input strings I'm afraid.
  • The other changes are great!

I'll manually transfer the changes you made to the code base, so you don't have to redo the PR. I'll close this PR once I'm done with that.

Thanks!

@DimonSE
Copy link
Contributor Author

DimonSE commented Aug 11, 2023

Thank you, this is great

@badlogic badlogic closed this in 066a152 Sep 6, 2023
badlogic added a commit that referenced this pull request Sep 6, 2023
@badlogic
Copy link
Collaborator

badlogic commented Sep 6, 2023

@DimonSE sorry for this taking so long! I've now transfered the changes to _readVertices() and spAnimation_create(). They are available in both the 4.1 and 4.2-beta branches. Thanks!

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

Successfully merging this pull request may close these issues.

2 participants