davidjoffe / dave_gnukem

Dave Gnukem is a cross-platform 2D scrolling platform shooter inspired by Duke Nukem 1
GNU General Public License v2.0
75 stars 22 forks source link

Move away from printf-style formatting #203

Open davidjoffe opened 9 months ago

davidjoffe commented 9 months ago

I know some may disagree, but after much consideration I feel it's better to completely move away from these types of functions (so-called printf-style in C/C++, famous, perhaps infamous, i.e. functions using "%d" "%s" etc. to format strings), as even if it's done 'perfectly correctly' and even if it's done 'safely' with dynamically resizable buffers and thread_local variables, and even if nobody ever makes mistakes in the formatting arguments (which can sometimes be subtle and platform dependent e.g. when moving from 32-bit to 64-bit say), it STILL in some cases requires locks even with thread_local buffers. Also even though I love thread_local, we want to avoid UNNECESSARY OVER-use of thread_local because it incurs a tiny extra performance penalty every time a thread is created (and I'd like an architecture that allows scaling). Also for most simple string logs etc. there isn't even formatting and then it's unnecessary performance overhead to do "printf("foo") - better to use functions where (1) it does not need to parse for formatting in the first place (thereby reducing risk of accidental mistakes too) and (2) such functions can potentially gain slightly further from constexpr compile-time strlen calculation of string literal to avoid in some cases an extra unnecessary strlen call at runtime (e.g. for something like "LOG("foo") if the compiler can calculate strlen for us - as it can - likewise with std::string::append(char*,len)) we get tiny extra performance.

This may be negligible for most stuff, but potentially in performance-sensitive parts of code it may help - especially for gamedev.

So these alternatives can be both faster, and safer from a bug and security perspective. And functions like std::to_string(n) instead of "printf("%d",n) can be automatically thread-safe without need for locking or buffers (thread_local or not) - desirable if one generally wants to start doing threading stuff - even though we don't currently have threads.