mikke89 / RmlUi

RmlUi - The HTML/CSS User Interface library evolved
https://mikke89.github.io/RmlUiDoc/
MIT License
2.74k stars 299 forks source link

Reduce the amount of static initialization in the library #663

Open AlexMax opened 1 week ago

AlexMax commented 1 week ago

I use RmlUi on a system that is behind an NDA, so I cannot mention it by name. However, I have discovered that on this system, in certain circumstances, we are bitten by Static Initialization Order Fiasco. To use very general terms, we were attempting to use a memory profiler on our app, and we discovered that because there were certain data structures that were initialized during static initialization, they were being allocated before the memory profiler had a chance to initialize, which caused allocation functions to get very cross with us and segfault.

Even when you're not dealing with strange platforms, I think that it is good practice in general to avoid the use of globals in a library, as this lengthens the amount of time between static init and hitting main(argc, argv). We have worked around these issues in our codebase with a global singleton that constructs on first use, something like:

Globals& GetGlobals() { static Globals s_globals; return s_globals; }

Something similar for RmlUi might be handy, since it would mostly be a copy-paste job and not require a significant re-architect of the entire library. A downside is that accessing the initialize-on-first-use would be a tiny bit more expensive, since a function has to be called, and an implicit branch is added - however we imagine the performance impact would be negligible.

mikke89 commented 1 week ago

Hey, and thanks for the feedback.

Generally, I agree with you, globals should be avoided, for multiple reasons. Right now, certain parts of the API are based around globals (the interfaces in particular, and initialization), and it would require some effort to change at this point, and several breaking changes. There was some discussion around this in #489. I would also add that singletons have most of the same issues as globals. Hopefully, at some point, we can get away from them entirely.

I wouldn't really go out of my way to convert every global to singletons. However, I believe there are some particular parts that are causing the issues that you describe. In particular, we have some memory pools that are relatively heavy to initialize, some of which are done during global initialization. This is definitely bad, and fixing it should only require relatively small and non-breaking changes. So I am fully onboard with changing those. Do you know of other objects that are causing issues for you, other than the pools? I'll take a look around regardless.