
Thoughts on Modern C++ and Game Dev - lebek
http://www.elbeno.com/blog/?p=1598
======
arandr0x
I'm not in games but my industry is adjacent and I have the same gripes with
c++. (Which the author characterized very well.) Although build and debug
times definitely are an issue regardless of the performance of the hardware.

I find reading C++ "standards" papers onerous and feel like they're written in
a way that's deliberately inaccessible. I don't much like the idea of going to
CppCon -- even if my company funded it, which maybe they would, I feel like
I'd be marginalized for not using template metaprogramming, not knowing the
new hotness by heart, and generally being a proponent of C-with-classes. I
just feel like so much of the C++ "standards" work feels like it's led by
academics who think the concerns of working programmers like me are beneath
them.

Is there a way I can "get involved" and does my voice have any value?

~~~
mattnewport
If you want to get involved and for your voice to have value then you have to
educate yourself on the subject. Unfortunately too many of my former
colleagues in the games industry (I'm now in a "games adjacent" industry too)
fail to do this before complaining about C++ and have the same attitude of
"it's not fair that I should have to know what I'm talking about before anyone
will listen to my complaining seriously".

Videos of all CppCon talks from the last several years are freely available on
YouTube and if you took the time to watch them you'd see that many of them are
by working programmers and not academics, quite a few of them in the games
industry. You'd also learn that the committee is quite focused on simplifying
the use of the language and on finding more usable ways to get the benefits of
template metaprogramming. You would also find explanations of many features
that are more accessible than standards papers and occasional explanations of
why standardese is the way it is - nobody, even the most academic speakers,
claims to find the standard the most accessible way to learn about a new
feature.

~~~
arandr0x
I've read some of the drafts and the final spec of the APIs I care most about,
for example, the concurrency API (which I like a lot... I'm not solely
complaining!). Do I need to watch every talk on every C++ feature before
anybody in the C++ community will want to talk to me? Because I'm paid to
actually write code. (I mean normally. Today my boss isn't back from vacation
so you get to read my rants on HN.)

Here are the C++ subjects of interest to me:

* geometric primitives. Not having basic geometry by now is insane.

* concurrency, I think the API as it is is good, but some of the APIs around atomics (mostly the difference between compare_exchange_weak and compare_exchange_strong) are not clear, I have had to explain those to coworkers before. Why can't we have something called test_and_set like on atomic_flag that's an OK default? Also, while I perfectly understand why that's the case, atomics have deleted copy constructors and that tends to generate compiler errors. I don't get why compilers can't just generate default constructors that don't copy the atomic like all my coworkers keep having to write and potentially introduce errors in

* filesystem API, very excited for that but sort of worried it will not work on every platform and especially that it'll work terrible on windows. I have to write Windows/Linux/iOS/Android C++ so a bunch of my gripes are "the standard is inconsistently supported" and I supposed that's not the job of the standards committee to enforce... but maybe they could stop inventing new stuff for Microsoft to screw up...

* few other misc things. The fact X const& and const X& are both valid leads to every project having its own "standard" of const placement and it's not great to read, etc. not major stuff. But things that are of concerns to working programmers.

I'm not really _complaining_ , I love C++ and being a C++ programmer and you
couldn't pay me enough to go integrate idiosyncratic web frameworks. However I
think you must admit that the C++ _community_ , beyond the language itself, is
a little exclusive and not super friendly to people who are not as
knowledgeable as others. I have a little time to learn some of this stuff, and
I would be happy to, but I will never be an expert like most of the standard
committee is. Based on your message I think that makes me and my opinion not
welcome? If so that's OK, but, um, there's a lot more of me than there are of
them in this industry.

(edited for formatting)

~~~
mattnewport
The standards committee is a volunteer effort. Some of the most active
participants have employers who consider their involvement as part of their
job responsibilities so they are at least partly being sponsored by their
employers but plenty of people involved in the standardization process and
attending conferences are not paid by anyone for their participation and are
in fact paying the costs of attending out of their own pocket. Hardly anyone
in the C++ community is directly paid to sit around learning more about the
language. If you wanted a career where you didn't have to put in learning on
your own time to keep your skills current I think you picked the wrong one.

It's a fairly involved process to get a new library standardized.
Functionality that's not included in the standard library may be missing
because it's hard to get agreement on what is required, because there isn't
anyone sufficiently motivated to drive it through standardization or because
the committee just hasn't got round to it yet.

I don't consider this particularly problematic in many cases. Some
functionality probably shouldn't be part of the standard IMO. For example,
there's been some effort to standardize a 2D graphics library and I'm of the
opinion that should not be part of the C++ standard. I'm inclined to think the
same thing for geometric primitives, for similar reasons. Certain types of
library are better left to competing open source libraries for now I believe.

Implementations are not the domain of the standards committee. It's rather
inconsistent to demand relatively niche new library functionality for
geometric primitives at the same time as wanting the committee to stop adding
things to the standard faster than Microsoft can keep up however.

Concurrency is complicated and there are a lot of pitfalls which the standard
library has gone to great lengths to avoid. It sounds like you're
misunderstanding the best way to use atomics but without knowing more about
your use case I'm not clear exactly how.

Coding standards are not really the domain of the standard and some things
that have multiple possible ways to write them have to be maintained for
backwards compatibility. If you want to standardize things like const
placement however, tools for automatic formatting and transformation of C++
are getting better all the time thanks to clang/llvm.

C++ occupies a niche which necessitates it being a bit less beginner friendly
than some languages and a bit more demanding on users putting in the effort to
learn the language. That's what makes it fairly uniquely suited to certain use
cases. I don't see that as a bad thing. I don't really know what you're asking
for to be honest. My advice to anybody who uses C++ as a major part of their
career to invest a decent amount of time into learning it better though, just
as I'd advise them to spend time learning more in any domain that is a big
part of their professional life.

~~~
arandr0x
Thank you for replying in-depth, I didn't expect it. I actually agree with you
re: 2D graphics(I was aware of it already), I just think geometry is different
because it has wider applications. Your viewpoint is consistent though.

Again, I think concurrency is one of the parts the standard library does best.
(And I think part of the specifics of this is it has primitives like async and
future that are higher level and are much easier to explain. I happen to write
lock free data structures often enough that finding blog posts at a good level
to explain the API for atomic to my code reviewers is a need/bother for me,
but there are also plenty of concurrency use cases where I don't need atomics,
and I also read that there was a plan to allow parallel execution for most of
the algorithms in the standard lib, I don't know if that's in MSVC yet but
that's an example of things I like).

I don't blame the standards committee for implementors. In general, it must be
terribly difficult to be on the standards committee, and have to deal with
stuff implementors have already done, stuff they won't do, and stuff they are
telling you they are doing but will not do right in the end. OTOH, as a end
user, you have to understand that I have to deal with implementors, and they
affect how I think of a given C++ feature, some of which look awesome in the
text but are impractical because of implementor differences. I'm not alone:
every C++ dev I know has a subset of C++ features they have deemed
"practical", based on things like implementation performance, compiler error
messages, how many characters the function names have, etc., and part of the
problem is it's not the same subset for all C++ devs. Sometimes I wonder if
there shouldn't be a subset of the standard (and I don't mean the C subset!)
that's earmarked as beginner-safe and compilers could enforce the, well,
beginner-safeness of code that is meant to be foolproof... but I suppose your
angle is code meant to be foolproof should either never allow a beginner
within 50 feet of it or be written in Java (or Rust?). Which, I get.

I would like to clear up a misunderstanding that I think you had: I do not
spend zero time learning about C++. I'm not super confident and I think by HN
standards I am not very experienced in C++ (or anything else), I'm definitely
not at the level where people at CppCon would want me in the room, but people
at my workplace do come to me for help with that stuff a bunch of the time. I
tend to volunteer to explain newer or more complicated parts, etc. I'm a mid-
level dev generally and C++ is my main language, and I'm not significantly
more ignorant than my coworkers about it. If that is below the threshold at
which you will consider someone worthy of talking about C++ on the Internet,
maybe that's why C++ doesn't have that many beginner-friendly communities
around.

~~~
mattnewport
I have no threshold for when someone is worthy to talk about C++ on the
Internet. What I don't particularly like is people complaining about things
they don't seem to have made much effort to understand. I'm happy to answer
questions for people who genuinely want to learn about C++ (my top 5% ranking
for C++ answers on Stack Overflow attests to that I think).

There's never been a better time to learn C++ - there's a wealth of free
resources online from conference videos to blogs to podcasts like CppCast. C++
standardization is more active than ever and the language is getting better
with each update to the standard and there is a real effort to also make it
simpler which I believe is mostly succeeding. Implementations have also
improved a lot in recent years. It's just the pace of change is such that
there is work to do to effectively communicate that fact to people who don't
pay much attention to the development of the language.

I think if you want a long term career in this industry you need to dedicate
at least ~5 hours / week of your own time to professional development on an
ongoing basis. If you work with C++ on a daily basis then spending some of
that time working through CppCon videos (I like to watch at 1.25x speed) and
other free online resources is a good idea IMO. I'd also advocate writing a
bunch of small programs from scratch to explore unfamiliar features or
libraries. Working through programming interview type problems can be good
practice, or just try things out to satisfy your own curiosity. I'd say
getting in the habit of writing a small program to experiment with something
new was the biggest factor in increasing my comfort level and understanding of
the language.

~~~
arandr0x
> I think if you want a long term career in this industry you need to dedicate
> at least ~5 hours / week of your own time to professional development on an
> ongoing basis. If you work with C++ on a daily basis then spending some of
> that time working through CppCon videos (I like to watch at 1.25x speed) and
> other free online resources is a good idea IMO.

Then I know what I'm doing tonight. I like the computational geometry aspect
much better than the programming language part. The thing with C++ is very
often the stuff you don't know sneaks up on you at the worst time when
starting on a new library, or trying to reuse code more complex than you're
used to. It's strange to think of it as something to study, but 5h/week is
something I could do instead of more overtime.

>What I don't particularly like is people complaining about things they don't
seem to have made much effort to understand.

The main thing I was complaining about was C++ takes (relatively to e.g.
Python) a ton of work to understand accurately, but also to explain properly
to other people. You must know that from answering on StackOverflow too.
(There are features of C++ I don't use because I/my coworkers don't yet know
them, and studying will help me with that, but I can't complain about them
yet!) StackOverflow is actually great for C++ though, so thank you for
answering on it. Usually there's always an answer with a detailed explanation
even for strange code samples. Often it's through reading the other people's
questions that I can understand how a construct can be useful in practice.

~~~
mattnewport
In my experience C++ may seem more complex to understand initially than
something like Python but once you invest some time to really understand it
then it is much less mysterious / less of a black box than an interpreted or
JITed language, particularly when dealing with anything performance sensitive,
because nothing is hidden from you under layers of abstraction that persist at
runtime yet are relatively opaque to your debugging or profiling tools.

One of the nice features about C++ IMO is that there is very little "magic" in
the standard library. Unlike some languages, all the features of the standard
library can be implemented with standard language facilities that are
available to you for use in your own code. Some of the more complex areas of
the language however are there primarily to support library authors writing
very general code and you don't need to fully grok them to be an effective
user of the language. Learning about some of them over time however will
likely pay dividends for your own code even if you are not writing widely used
libraries.

------
deng
So, the solution to bad debug performance is essentially YAGNI? I'm afraid
that isn't a very convincing argument. If your code is several orders of
magnitude slower in debug mode, then this _is_ a problem. Simply downplaying
this with arguments like "single-step debugging is a last resort" or "just
write better tests" won't make this problem vanish. Just like exploding
compile times are not solved with "just buy Incredibuild".

But his argument fits well with C++'s history of finding exceedingly complex
solutions for simple problems. Want to have efficient matrix calculation?
Well, who needs native support for matrices when you can do the same with
expression templates and static polymorphism/CRTP (see: Eigen library).

The last section of the article says you either do nothing or you get
involved. I'm afraid it is missing the obvious third option: switch to another
language which actually supports your use case.

~~~
neutronicus
> But his argument fits well with C++'s history of finding exceedingly complex
> solutions for simple problems. Want to have efficient matrix calculation?
> Well, who needs native support for matrices when you can do the same with
> expression templates and static polymorphism/CRTP (see: Eigen library).

I have to defend C++ here - "native matrices" is under-specified. In practice,
"Matrix" is one of the leakiest abstractions in programming and you have to
care about representation and choice of algorithm pretty much from the get-go,
and IMO C++ is actually the best available option for managing that
complexity, especially when you're solving large systems in parallel (and it's
worth pointing out that one of the front-running open-source libs in this
space is written in C++[1]).

[1]
[https://github.com/trilinos/Trilinos](https://github.com/trilinos/Trilinos)

~~~
deng
For many projects you won't need that complexity. You just want to directly
map basic matrix operations to the usual BLAS/LAPACK calls. Fortran 90+ does
that job well, for instance, and performance will usually be better than a C++
library (yes, I've tested against Eigen and Armadillo, although that was years
ago). Combine that with the enormous compile times and the absolute ridiculous
error messages for even simplest syntax errors, and I never looked back.
Fortran may have a bad rep, but the newer iterations are actually pretty good
for that kind of stuff.

~~~
curlypaul924
I'm confused. Are you suggesting that Fortran is a good environment for game
development?

------
jayd16
I don't want to weigh in on the rest of the content but the characterization
of the game industry is pretty accurate in my experience.

I would expand more on the first bullet point of why game devs don't test.
Tests are anti-agile and game development is extremely agile. Usually you
don't know what kind of game you're making until you're done.

~~~
otikik
I think the reason is that tests have a very obvious up-front cost, while the
time they save is distributed in the future, in a non-immediately obvious way.
I still think that they end up saving time, with some exceptions like UI code,
which are more easily tested "by hand".

Game project managers are infamous for not being great planners, so it
wouldn't surprise me that they dismissed automated tests as "a waste of time"
or "something that we can't do now because we don't have time now" (so we end
up wasting more time in the end, having to do death marches, etc)

~~~
blktiger
Modern games have only increased the benefits a game studio can gain from
testing as well. Games are now moving into service territory which only
increases the amount of time spent maintaining the game while continuing to
add to it.

~~~
midnightclubbed
This. Determining when the effort should be applied is the tricky part. Games
are still hit driven and get cancelled/re-purposed during development. You can
spend a lot of QA engineering time developing systems to test functionality
that never ships (case in point would be Fortnight - the original shipped game
did not need to be tested against the current 100 player game instances and
huge load but they could have spent a bunch of time testing AI systems that
are no longer any part of the game).

~~~
blktiger
I don't disagree that it's important to understand when something is purely a
proof of concept vs something that will stick around to evaluate the costs.
However, the AI systems are still in Fortnite (and they even used those
systems for the Haloween event). The major money making part of Fortnite has
been the battle royale mode though. If they open up the main game to be free-
to-play similar to the battle royale mode those systems will probably end up
being used quite a bit.

------
overgard
A few thoughts:

* None of the problems that have been commented on are unique to the games industry at all. Slow debug builds suck for all C++ developers and weird template meta-programming is confusing for practically everyone.

* He makes these broad hand-wavey statements like "individuals don't feel pain from slow compile times", or "big companies can just can throw processor power at it" to which I would say, BS. Fast iteration in C++ is really hard because of the delay and it's a big problem for everyone.

* "Participate more" \-- isn't that exactly what people are doing on twitter? Not everyone can go to CppCon.

~~~
andrewmcwatters
My question is, where are all these "big companies" who can throw more
processor power at these problems? Because frankly, every major company I've
been at uses the same commodity or cloud hardware everyone else does, so I
just don't see it. It's a moot point.

Rarely do I see workstation-grade hardware in the wild, and when I have,
they're build slaves that are incredibly anti-agile.

~~~
mattnewport
EA I know gives developers very powerful workstation class developer machines
because I used to work there and have friends who still do and if anything it
sounds like they've got even more powerful on a relative basis since I left.

------
youdontknowtho
Whenever the response to a twitter argument is "get involved and make the
change you want to see happen" you can expect absolutely nothing to change.

Part of this is just people complaining on a platform that over values short
pithy complaints.

------
pulsarpietro
I am a bit puzzled by this:

"Before about the early 90s, we didn’t trust C compilers, so we wrote in
assembly."

There a lot of games released during the 80's, were they really all written in
assembly ?

[https://www.myabandonware.com/browse/year/](https://www.myabandonware.com/browse/year/)

I don't have experience in the game industry at all, I must add.

~~~
vardump
Heavier things, like graphics processing were typically written in assembler.
Or sound mixing.

Some things like texture mapping you could only write in assembler, because
you'd need to use x86 lower/higher half of word (like AL and AH registers) due
to register pressure. Spilling to stack could have caused 50%+ slowdown.

486 era you needed assembler to work around quirks like AGI stalls.

On Pentium the reason for assembler was to use FPU efficiently in parallel
with normal code (FPU per pixel divide for perspective correction). Of course
you also needed to _carefully_ hand optimize for Pentium U and V pipes. If you
did it correctly, you could execute up to 2 instructions per clock. If not,
you lose up to half of the performance (or even more if you messed up register
dependency chains, which were a bit weird sometimes).

One also needs to remember compilers in the nineties were not very amazing at
optimization. You could run circles around them by using assembler.

Mind you, I still need to write some things in assembler even on modern x86.
But it's pretty little nowadays. SIMD stuff (SSE/AVX) you can mostly do in
"almost assembler" with instruction intrinsics, but without needing to worry
about instruction scheduling and so on.

~~~
CoolGuySteve
Last time I used SSE intrinsics, which was GCC 4.9 I think, I had a lot of
trouble with register usage. It looked like it was compiling down to use only
one SSE register for everything instead of parralelizing across them.

I tried the same algorithm in godbolt with some clang versions and it was
slightly better, using two or three registers, but not by much. So I had to
break it into inline assembly.

I wonder if GCC has improved since then.

~~~
exDM69
> I wonder if GCC has improved since then.

Yes, it has. I've written a lot of SIMD code and spent a good amount of time
reading the compiler assembly output and there has been huge improvement over
the last decade.

GCC register allocation wasn't great, then it got better with x86 SSE but
still sucked at ARM NEON, and now it seems to be decent with both.

Clang was better at SIMD code before GCC was. It was equally good with SSE and
NEON.

In my experience, compilers are much better than humans at instruction
scheduling. Especially when using portable vector extensions, you don't have
to write the same code twice and then tweak the scheduling for every
architecture separately.

~~~
vardump
> In my experience, compilers are much better than humans at instruction
> scheduling.

It'd be more accurate to say they're much better than humans when the
heuristics or whatever they use works. Sometimes the compiler messes up badly.

The workflow is often to compile and then examine disassembly to see whether
the compiler managed to generate something sensible or not.

Other issue is that compiler pattern matching is sometimes not working and
generating correct SIMD instruction. Even when data is SIMD width aligned. For
example, recently I saw ICC not generating a horizontal add in the most basic
scenario imaginable. * shrug *.

~~~
AnIdiotOnTheNet
Things like this make me question the wisdom of ever using higher level
languages. We took the path of abstracting our description of what we want to
happen away from processor instructions with the idea that we could write code
that could then compile on multiple architectures without changes, but the
reality is that we still often need to special case things even without
performance considerations, and the farther we abstract the more performance
seems to be impacted and the more often we seem to end up jumping through
abstraction hoops rather than getting things done.

The minimalist in me wonders if maybe just using some kind of macro system on
top of assembler plus a bytecode VM with the ability to drop to native
instructions wouldn't ultimately be better.

------
CoolGuySteve
Is Visual Studio really the best debugger?

Every time I use it I get really frustrated by the difficulty of entering
complex instructions. The GUI is more discoverable but I find myself missing
gdb ‘s functions and parser.

However, one thing in gdb that’s become steadily worse is the ability to
evaluate STL’s operator[] and the like in optimized code, with the debugger
frequently whining about inlining. It’s pretty horrible having to decipher the
_m_data or whatever of various implementations.

I’m actually not sure if gcc is not compiling the inlines into the object code
(I thought it was required by the standard) or if gdb just can’t find them.

~~~
pjmlp
Yes, given the graphical tooling for multi-core, GPGPU, data visualization,
edit-and-continue, mixing Assembly with code (even on .NET), interaction with
GUI components on WPF/UWP apps,...

~~~
CoolGuySteve
That kind of gets to the heart of what I’m saying. These graphical tools are
great as long as they do what you need. But they are less composable and
customizable than an expression parser.

Like in the article he mentions not being able to see custom data types, but
my .gdbinit has a few pretty printers in it for exactly that purpose.

And when you do get something customized in MSVC like a specific PGO build or
something, it tends to be tightly coupled to that project. It’s less easy to
cut and paste into another project since the primary interface is really a
dozen little text fields modifying XML somewhere.

~~~
pjmlp
VS supports displaying custom types.

Regarding gdb, during the mid-90's I got by calling it from XEmacs, until I
discovered DDD.

I got spoiled with Borland debuggers, typing n, s, l, p all the time and
drawing structures on paper gets tiring after a while.

------
arka2147483647
>Epilogue (... snip ...)

> 1\. Do nothing (...) You can deal with that by imposing rules on what is and
> isn’t allowed in your codebase, (...)

This is what everybody is already doing in gamedev

> 2\. Get involved (...) C++ committee participation is open to everyone.
> (...)

Most game dev studios are Small or Mediums sized companies, and don't really
have the time to waste in Committee meatings...

~~~
Jyaif
> Most game dev studios are Small or Mediums sized companies, and don't really
> have the time to waste in Committee meatings..

Irrelevant. What counts is where the C++ game devs are, and it's in the big
companies. And participating in the design of a language is not a waste of
time...

~~~
SomeHacker44
Its a matter of perspective, what constitutes a waste of time.

If you are under pressure to ship something now/soon, and may not exist as a
company in the next standards cycle, then it is probably a waste of time for
that company.

------
pmarin
>Stop going to GDC as your one conference per year and start going to CppCon.

In fact the most popular CppCon video in Youtube is from Mike Acton: “Data
Oriented Design and C++”

------
shmerl
Game developers should start using more Rust.

~~~
rafaelvasco
Yeah it's an awesome language. Has its downsides (language enforced memory
micromanagement is a good thing but can get annoying sometimes.) but it's one
of the best we have now. For now i'll stay with my beloved C#.

~~~
shmerl
C# doesn't sound like a good option for games development though (except may
be for scripting used in various engines).

It's now dominated by C++ for a good reason, since it requires tight
performance control. So Rust is a valid candidate for fixing C++ issues. C# -
not really.

------
edoo
Most industry game dev is also done on top of C++ engines and libraries. I can
see Go being used in the near future as the big engines offer bindings but I
bet in 5-10 years the average startup is using something like C#. It is slow
as beans but eventually CPU speed will make it much more reasonable for real
use. The Unity engine is a good example. It has a weird easy powerful super
bloated paradigm.

~~~
jokoon
You just mentioned 2 garbage collected languages on a game dev topic. I don't
think they're adequate. Remember how the article was very insistent about
being able to control memory and CPU resources. Those are one of the few
reasons C++ is not dead.

Rust? I don't see it either.

~~~
walkingolof
Garbage Collection is not per default something bad, even in game development,
its a method of memory management, just like reference counting, or manual
memory management.

If you are allocating memory in your renderloop, your likely doing it wrong.
Allocation outside of this critical path, well, chose your poison.

GC will consume more memory, but likely to be faster when it comes to
allocating and deallocating large amount of small blocks.

Reference counting, if you do it properly (to avoid thread starvation), is
costly. Cheap atomic reference counting, involves a calculated risk that you
may have threads hanging.

Manual memory management, well, we all know the cost of that :)

That being said, many many games are today developed with Unit which uses C#
as its primary programming language.

~~~
HippoBaro
Sure, you can. But then you need to manage when GC triggers. Because if you
don't, you'll drop frames. And then the real choice is between C++ where there
is (little) extra work getting RAII correct vs GC languages where you need to
keep preventing GC up to a point where it's okay to freeze the universe.

~~~
ulber
A clever approach for VR that was used in Downward Spiral [1] (a Unity game)
is to add a periodic eye blinking effect and trigger the GC on a black screen.

[1] [http://www.3rdeyestudios.fi/downward-spiral-horus-
station/](http://www.3rdeyestudios.fi/downward-spiral-horus-station/)

------
mark-r
Maybe the QA folks are worse off in game dev companies, but they seem to be
second class citizens everywhere else too. Which is a pity, since as stated
they are worth their weight in gold. A developer has a mindset of how do I
make this work, a QA person has a mindset of how do I make this break - they
are completely complimentary.

