News for hackers. Stuff that matters.
Re:A Taxonomy of Technical Debt by drawkbox on Wednesday April 11, 2018 @02:01PM (#16813706)
At pretty much every game studio there is an epic internal battle of standard libs vs custom. std::string and [some custom string class] here it is AString is usually the spark. A constant of internal game development is that they think they can always build better strings, lists, dictionaries, collections etc than the standard lib, basically thinking the standard lib is as it was in the 90s and all the work that went into them is bunk. In some cases if you are really pushing memory and not writing custom allocators or using something like boost then yes, but in most cases the technical debt of custom classes written by an ancient from generations ago internally is more technical debt.

> One of the best examples of MacGyver debt in the LoL codebase is the use of C++’s std::string vs. our custom AString class. Both are ways to store, modify, and pass around strings of characters. In general, we’ve found that std::string leads to lots of “hidden” memory allocations and performance costs, and makes it easy to write code that does bad things. AString is specifically designed with thoughtful memory management in mind. Our strategy for replacing std::string with AString was to allow both to exist in the codebase and provide conversions between the two (via .c_str() and .Get() respectively). We gave AString a number of ease-of-use improvements that make it easier to work with and encouraged engineers to replace std::string at their leisure as they change code. Thus, we’re slowly phasing std::string out and the “duct tape” interface between the two systems slowly shrinks as we tidy up more of our code.

So now there are two string classes, that is technical debt... and one should be consolidated on and the arguments against std::string are sometimes valid but you can also do custom memory allocators or use better standard lib iterations.

EA even rewrote the whole standard lib EASTL [1] to adjust for some of these issues i.e. fragmented memory. Some games require it, some it is pure ego in game development teams. Game development teams have the highest ego driven development (EDD) I have ever seen and lots of tricks that take five minutes (but add 2-3 months to testing due to five minute solutions) but are more spaghetti than templates that write templates.

The one problem that comes about with your own standard lib or thinking you are better than boost or similar, is that the learning curve on the internal lib replacements add technical debt and start up costs, and the original guy that wrote them is long gone usually. Also, in the end portability suffers as there is invariably 3-4 versions of the internal libs.

Developers have to weigh the technical debt of your own custom classes outside standard libs and see if that outweighs the memory issues that may arise. Today most machines are not as affected by memory fragmentation issues and there is more cpu/memory to go around, and where they are you can write custom allocators for std/stl or use something like boost.

I do love Riot Games and all game development teams just I have never worked in one or with one that doesn't have the standard lib vs custom battle and wastes lots of time when one isn't standardized on or when not necessary. Some games and game engines require it, where they do you should fully commit one way or the other. Though going custom leads to slowdowns in coding for new devs and invariably there will be multiple versions of those internal libs over time that add up in the debt department.

[1] https://github.com/electronicarts/EASTL

Re:A Taxonomy of Technical Debt by badloginagain on Wednesday April 11, 2018 @03:32PM (#16814661)
One of the biggest problems of this is the tribal knowledge that develops around it. I worked at a studio that had something very similar to EASTL, but had joined the studio after an exodus of senior people.

It meant I had no idea how to use the custom libs. No documentation, no one left in the office to tell me how its used, no Stack Overflow to answer even trivial questions.

I left after less than a year. The studio closed down 2 months after I left.

Re:A Taxonomy of Technical Debt by mattnewport on Thursday April 12, 2018 @10:48AM (#16821467)
EASTL mostly doesn't have this problem because it as far as possible is a compliant implementation of the STL with a few specific extensions, mostly around memory management. It's not a library that provides STL-like functionality with a different API. Much of the custom allocator stuff has finally now been superseded with polymorphic allocators in C++17.

Source: former maintainer of EASTL (not the original author).

Re:A Taxonomy of Technical Debt by badloginagain on Thursday April 12, 2018 @02:14PM (#16823469)
I would imagine that being a larger organization, there are dedicated resources for at least some documentation/POC's for questions/changes/etc.

The smaller the company, the less resources you have to maintain, the more issues you're going to run into.

Re:A Taxonomy of Technical Debt by WorldMaker on Wednesday April 11, 2018 @02:32PM (#16814009)
There's absolutely a "problem domain debt". If you are a game company, your problem domain that gets you paid is your game(s). Time spent rebuilding standard libraries is time not working directly on the game, and maybe time not getting properly "paid". Meanwhile, there are already people paid to work on the standard libraries, and its their job to make those work and continue to improve them.

Certainly there are tradeoffs where you may have to know the standard libraries well enough to know their performance characteristics, or how best to mitigate worst case scenarios, but if the people paid to build standard libraries are doing their jobs (that you pay them for when you buy that compiler), it should be less debt work to workaround an existing solution than build one from scratch.

Re:A Taxonomy of Technical Debt by hinkley on Wednesday April 11, 2018 @07:33PM (#16816780)
If I had a nickel for every jackass who thought he understood URL parsing well enough to do it by hand instead of using the goddamned builtin library like a sane person and get all of its sanity checks and corner cases handling for free, I could retire (and would be a lot less bitter).
Re:A Taxonomy of Technical Debt by ryandrake on Wednesday April 11, 2018 @03:22PM (#16814567)
It’s not just game studios who rewrote the standard library. I’ve seen non game companies with their own containers too. For those cases, it’s always just very old legacy code that nobody wants to touch, but if they were to do it again fresh today, they’d just use what comes with the language.

For places that have their own legacy containers and actively try to move more code to them—I dunno! I think at some point back in the 90’s the standard library got the reputation of being junk (perhaps rightfully) among game programmers, and this belief has been cargo culted all the way into 201x. Who knows.

Re:A Taxonomy of Technical Debt by brann0 on Wednesday April 11, 2018 @05:03PM (#16815612)
You're missing the point of reimplementing some or all of the standard libs. Similarly, disabling C++ exceptions and RTTI is a very common practice in gamedev.

Sometimes you reimplement a certain standard class (vector, string...) to adapt it to the very needs and usage patterns you have. Standard libs tend to be too general, plagued with allocations and other useless (in this specific context) behaviors that may negatively impact your performance/cache friendliness/memory fragmentation...

I agree a simple tiny game doesn't need all of these but when you need to squeeze all the performance you can there's no other option.

So please, do not just dismiss all the gamedev wisdom like that.

Re:A Taxonomy of Technical Debt by drawkbox on Wednesday April 11, 2018 @05:45PM (#16816044)
> You're missing the point of reimplementing some or all of the standard libs. Similarly, disabling C++ exceptions and RTTI is a very common practice in gamedev.

I clearly stated there are good reasons to do so and some games do require it. Mostly though they don't.

> disabling C++ exceptions

stl::throw is pretty lightweight unless you use the exception objects, you can not catch exceptions, and you can also pass -fno-exceptions.

> RTTI

RTTI merely helps with casting, usually none of that is going on at runtime as game loops need to be clean and perform zero allocations if possible, it should be already loaded up in memory, architecture of the game loop and game can remove this concern. You can also disable RTTI with -fno-rtti and enable it per class with virtual void nortti(); per class or on ms compiler __declspec(novtable) per class.

Rarely do exceptions or RTTI affect the game loop and framerate as most of that should not be needed during runtime game loops.

Usually the complaints that are valid are about allocations/fragmentation but you can also write custom allocators and other solutions and like you mentioned the code style/api style. It can also be a simplification not using stl but usually things start to grow in custom libs to re-implement much of the same functionality.

>> EA even rewrote the whole standard lib EASTL [1] to adjust for some of these issues i.e. fragmented memory. Some games require it, some it is pure ego in game development teams.

In engineering there has to be a GOOD REASON(s) to start maintaining buckets of new code and libs. There are also ways to do it that still allow for most of the standard and promote documentation and understanding to it.

EASTL is a great way to go about it and I linked to it to demonstrate that.

I was mainly calling out using both standard and custom, that seems like more technical debt, if you truly do need custom libs then go all in. Having both lead to more problems but understand there is weight/debt to it and it isn't always better.

> So please, do not just dismiss all the gamedev wisdom like that.

In no way did I dismiss it, I just said there is a constant of this battle (stl/boost/others vs custom) in all gamedev studios and many times it is unnecessary bike shedding and yak shaving that doesn't have a runtime difference on the game or make the game better.

Find me a game studio that doesn't have a stl/standards vs custom battle and I say... wait for it...

Re:A Taxonomy of Technical Debt by jrs95 on Wednesday April 11, 2018 @03:04PM (#16814377)
You would think the approach taken with this would be to just use the standard libs until they're actually contributing to a bottleneck and then worry about optimizations. Doing it prematurely does seem to be a problem. Though I don't think having custom alternatives to parts of stdlib are bad if you're actually making a meaningful optimization.
Re:A Taxonomy of Technical Debt by ryandrake on Wednesday April 11, 2018 @03:26PM (#16814616)
Premature and/or misplaced optimization. It’s kind of funny that they worried so much about std::string’s performance that they rolled their own, yet have this big honking lua layer thunked on top of everything for game logic. Wow!
Re:A Taxonomy of Technical Debt by LtRandolph on Wednesday April 11, 2018 @04:42PM (#16815369)
While we're not perfect, I'm happy to defend this decision. ;-)

We did a ton of tracing and perf/memory captures to identify that string allocations were a significant drain in many locations in the code. We don't see those issues with our other uses of std:: (vector, unordered_map, set, etc.), just with std::string. So it was a logical place to do targeted optimization.

We did that optimization before lua because of the fact that there's a very clean way to make the foundational debt into MacGyver debt, since there's a trivial conversion between std::string and AString. Sadly we haven't been able to come up with any bite-sized moves that we can do to phase out the wasteful use of lua as kvp storage buckets. It's an all-or-nothing problem that makes it a much bigger chunk of work to undertake.

Re:A Taxonomy of Technical Debt by brann0 on Wednesday April 11, 2018 @05:11PM (#16815704)
Great answer, thanks for the insight. I'm really puzzled at how many people aggressively answers when someone refuses to use standard libraries (or practices).

We were in a similar situation and using our own string implementation improved performance and reduced memory fragmentation.

Some people refuses to accept that certain software cannot rely on general purpose libraries and need to roll their own solution adapted to their specific needs.

Re:A Taxonomy of Technical Debt by ryandrake on Wednesday April 11, 2018 @05:18PM (#16815778)
Thanks for both your answers. It was not my intention to come off as aggressive there. Key takeaway is to measure rather than take it on faith that the library is the bottleneck. Sadly not everyone does measure.
Re:A Taxonomy of Technical Debt by drawkbox on Wednesday April 11, 2018 @03:57PM (#16814881)
Not only that, if you want good framerates and 60fps you aren't allocating at runtime, anyone who is doing that at a game dev studio is taken out back and either shot or to work on the cow clicker.

Usually standard lib vs custom arguments end up in the weeds like tabs vs spaces at game companies but ultimately it has almost nothing to do with framerate or runtime. Largely it is about that EGO. Why maintain a standard lib instead of improving gameplay and networking? Well some want to be a lord in their feifdom where they are the controller the code and the ring.

Riot Games has std::string and AString, but what happens when player two enters the game and you got BString? Then BString invites its friends and you got CString and DString. Now your 'standard' has many standards and is more standardy and like warring lords within internal factions like a Game of Thrones.

Re:A Taxonomy of Technical Debt by VyseofArcadia on Wednesday April 11, 2018 @03:52PM (#16814823)
My company's string container is definitely MacGyver debt. At some point in the distant past we had to worry about having both Pascal-style and C-style strings...