Live data from Hacker News

Modern C++ gamedev: thoughts and misconceptions

vittorioromeo.info

201–210 of 221 posts

Re: Modern C++ gamedev: thoughts and misconceptions

#201
post #111

Earlier quoted context omitted.

Perhaps the people who dislike auto in C++ would also dislike the equivalent feature in other languages but they just happen to not work in them? I know i do not use any of the languages you mention, for example - and if i did, i'd explicitly write any type names.

I don't think so. auto adds some more complications in C++ than var or let in other languages. Consider "const auto& a = x" vs "auto a = x". What exactly is the type of a? It depends.

Auto makes it harder to know the type in question, if C++'s auto is slightly more cryptic than var or let in other languages, doesn't really matter that much if what you dislike is not knowing the type in question in the first place.

But honestly i can only talk about me here, i can't guess why some imaginary other developer who dislikes a feature does dislike it.

Re: Modern C++ gamedev: thoughts and misconceptions

#202

Earlier quoted context omitted.

Perhaps the people who dislike auto in C++ would also dislike the equivalent feature in other languages but they just happen to not work in them? I know i do not use any of the languages you mention, for example - and if i did, i'd explicitly write any type names.

> Perhaps the people who dislike auto in C++ would also dislike the equivalent feature in other languages but they just happen to not work in them? How do you reconcile that world view with the fact that people are shipping billions of line of codes that obviously work in languages where until recently you couldn't even write any type anywhere (JS, Python) ?

I'm not sure what is there to reconcile or even what world view you refer to. Personally i do not use these languages much and when i do it is usually very short code and looks very different to code i'd write in a language with static strong typing.

Re: Modern C++ gamedev: thoughts and misconceptions

#203
post #110

Earlier quoted context omitted.

Yeah, this is exactly what i dislike - unless the declaration of "vec" is somewhere close by (and assuming it isn't itself "auto" :-P) you have no idea what "i" is. Especially when that "auto i : vec" should have instead been "auto& i : vec" or "const auto& i : vec" and now you are at best wasting cycles and at worst writing to copies that will soon be discarded, ending up with a bug that can be very hard to spot.

If the type is not obvious one can also write for(Class entry : container) This is still an uncontroversial improvement over having to typedef or use auto for the iterator.

Sure, that is what i'd probably write myself too.

Re: Modern C++ gamedev: thoughts and misconceptions

#204
post #98

Earlier quoted context omitted.

> An all or nothing approach to auto ends up being silly I already wrote that there are some cases where auto is necessary (usually when used with more recent C++ features). > especially if an IDE is there to expand complex type information And i also already wrote that this information is not only often cumbersome to obtain but also such an IDE is often not available - e.g. in a web-based code review tool which also…

What I'm saying is that auto is very useful and not an exotic or niche feature, it just works the best when not using it in places where a type definition is already small or direct. This usually means types that are from inside the scope of another class. Compound types that are used frequently can actually be aliased. Also writing programs that are clear when reading from plain text is great, but I don't think that…

Well, i already wrote about my thoughts on auto, so i do not see a reason to repeat them.

However, about IDEs, you still ignore that code is not only worked with inside IDEs - i already wrote twice the case of a code review tool... have you ever worked on a team with code reviews done by a web-based tool? Or even with a source control program that you want to check the differences between commits that someone else made long ago (they may not even be at the company anymore) and the diff tool obviously has no idea about types and such?

There are many reasons for why you need to work with code outside of an IDE and none of them have to do with using Notepad to write the code.

Re: Modern C++ gamedev: thoughts and misconceptions

#205

Earlier quoted context omitted.

...which you should avoid as much as possible do. Passing std types across API boundaries is a code smell.

What? That's one of the primary motivations! "I have created an object and will pass its unique ownership to you." -> std::unique_ptr "This routine needs a function that takes two ints and returns a float (without putting all my code into headers)." -> std::function . Can you elaborate in what circumstance you should not pass std::types across API boundaries?

The heap allocation is an implementation detail.

std::function is useful in some situations, but "without putting all my code into headers" is not a good argument.

Re: Modern C++ gamedev: thoughts and misconceptions

#206
post #183

Earlier quoted context omitted.

"no abstract frills attached" I can't tell what you think a frill is, but I can't square that statement with the rest of your post, and with the OP. Higher-level constructs might require language features like template metaprogramming, or a level of indirection. There are a few ways in which you can have "the same sort of code".

If you're doing foo a lot, you make a foo() function. That doesn't mean you have to create a pure virtual FoolikeOperation class and FoolikeOperationFactory, a concrete ActualFooFactory and an ActualFooOperation class.

Suppose you do foo a lot. And sometimes you need to do either foo or bar inside of baz.

You can pass a flag to baz, to choose either foo or bar. Now you have a closed set of possibilities. If you want to extend the functionality e.g with a plug-in, or got any other reason you want to avoid committing to the choice, then you either need

1. first class functions, so that you can pass in foo or bar or whatever.

or if you don't have first-class functions, then you need a

2. FooLikeFactory to make a FooLike object based on a runtime value (e.g. read from a configuration file), and then you can call your FooLike object from baz.

I like the quote that design patterns are bug reports against a language. The factory stuff you're talking about doesn't just exist for fun. It solves an actual problem. I hate Java as much as you do, I'm sure, but I value understanding the reason the patterns exist before I decide to just use a language where I don't need to do any of that stuff.

Re: Modern C++ gamedev: thoughts and misconceptions

#207
post #185

Earlier quoted context omitted.

While Java isn't perfect, it was more lack of skills of Minecraft developers than anything else. Using classes for everything with a full OOP approach, instead of DOA and ECS, with tons of new in hot paths, no wonder it had performance isuses. This was discussed in some Minecraft forums, https://www.reddit.com/r/programming/comments/2jsrif/optifin... It basically boils down to > Why is 1.8 allocating so much memory?…

How would avoiding GC even work? As far as I know that Valhalla thing still isn't there - wonder if it ever comes. Last I used it, you could only have "structs" together with GC. Maybe there is just no practical way to do this? What prominent examples are there? I remember a story of a HFT trading software written in Java. Supposedly it had big issues with GC. That's why they built a system where multiple threads wou…

But that is exactly what you do when going after performance in game development, even in C and C++, and it isn't less ugly by using those languages instead of Java.

There is an EA available for Valhalla and there is now the roadmap to incrementally bring such features into the platform. Java 14 has a new native memory support as experimental and it might reach stable already by 15.

https://jdk.java.net/valhalla/

https://cr.openjdk.java.net/~briangoetz/valhalla/sov/01-back...

https://openjdk.java.net/jeps/370

The problem why it is taking so long is engineering effort to keep ABI compatibility, namely how to keep 20 year old jars running in a post Valhala world, while at the same time migrate value like classes into real value types.

Java's biggest mistake, from my point of view, was to ignore the GC enabled systems languages that had value types, non traced references, and AOT compilation from the get go, then again I guess no one on the team imagined that 25 years later the language would be one of the choices in enterprise computing.

Back to Minecraft, the game isn't Crysis or Fortnight in hardware requirements, so a language like Java is quite alright for such game, what isn't alright is what the new development team apparently lacking experience eventually ended up doing to the game engine.

If one is to believe a couple of posts like the one I referred to.

Re: Modern C++ gamedev: thoughts and misconceptions

#208
post #207

Earlier quoted context omitted.

How would avoiding GC even work? As far as I know that Valhalla thing still isn't there - wonder if it ever comes. Last I used it, you could only have "structs" together with GC. Maybe there is just no practical way to do this? What prominent examples are there? I remember a story of a HFT trading software written in Java. Supposedly it had big issues with GC. That's why they built a system where multiple threads wou…

But that is exactly what you do when going after performance in game development, even in C and C++, and it isn't less ugly by using those languages instead of Java. There is an EA available for Valhalla and there is now the roadmap to incrementally bring such features into the platform. Java 14 has a new native memory support as experimental and it might reach stable already by 15. https://jdk.java.net/valhalla/ htt…

In C and C++ you don't need to make int-arrays. You can group data that is accessed together in structs and keep arrays of these structs.

With regards to performance, there must be some fine art in splitting structs into smaller structs, and keep them as parallel arrays, but there is also a limit to it. At some point you will need too many pointers to point at the same position in all these arrays.

I've never cared to split a lot, since it makes code harder to read. My guideline has always been to optimize for modularization: In OOP there tend to be large objects containing links to "all" related information. That violates the rule of separation of concerns. With parallel arrays you get perfect separation of concerns. One parallel array doesn't even need to know that there are others.

> Back to Minecraft, the game isn't Crysis or Fortnight in hardware requirements, so a language like Java is quite alright for such game, what isn't alright is what the new development team apparently lacking experience eventually ended up doing to the game engine.

I'm not in a position to judge, and I've never even played it, but it seems to me that Minecraft has a lot of voxels to maintain. Also massive multiplayer requirements?

Re: Modern C++ gamedev: thoughts and misconceptions

#209
post #207

Earlier quoted context omitted.

But that is exactly what you do when going after performance in game development, even in C and C++, and it isn't less ugly by using those languages instead of Java. There is an EA available for Valhalla and there is now the roadmap to incrementally bring such features into the platform. Java 14 has a new native memory support as experimental and it might reach stable already by 15. https://jdk.java.net/valhalla/ htt…

In C and C++ you don't need to make int-arrays. You can group data that is accessed together in structs and keep arrays of these structs. With regards to performance, there must be some fine art in splitting structs into smaller structs, and keep them as parallel arrays, but there is also a limit to it. At some point you will need too many pointers to point at the same position in all these arrays. I've never cared t…

Fair enough, however regarding massive multiplayer requirements most game shops are anyway using Java or .NET on their backends, as you can easily check going over their job adverts.

As on the client side, proper coding plus offloading stuff into shaders already goes quite far.

And even in the debatable point that Java isn't the best language for any kind of game development, well maybe Mojang would never have taken off if Markus had decided to prototype the same in something else.

Nowadays the Java version is only kept around due to the modding community, as the C++ version is found lacking in this area.

Re: Modern C++ gamedev: thoughts and misconceptions

#210

Earlier quoted context omitted.

Well, readability is like this. It's not a property of the code alone, it's an emergent property based on both the code and your knowledge as a reader. It's very, very subjective, which our little disagreement here proves. Basically, the same code using the same feature can be both insurmountable wall of text and an elegant, readable solution - depending on your background, current knowledge, and personal taste (amon…

It isn't just about knowledge, but also about how much knowledge you'd need to keep in your head just to read something - the least the code requires from you before you even start reading the code, the more you can focus on understanding the code itself. And even when you know about the features shown, it still is hard to follow the flow. I mean, i do know about lambdas in C++ and have used them a lot, but i can sti…

> but also about how much knowledge you'd need to keep in your head just to read something

Yeah, but the effect of this is greatly overstated most of the time. As I said, given enough effort, you can learn - and learn to keep in your head - anything. It matters in the short term, while you're learning, but in the long run, once you've learned and internalized all the required information, it stops being relevant.

It's probably harder to learn to read and write kanji instead of the Latin alphabet. For most people, that difference matters for a few years in their childhood, but once they have the characters drilled into them, it no longer matters: they can read and write as well as any Westerner.

The same is true for (natural) languages: some are inherently more complex and hard to learn than others, yet once you become fluent, you stop noticing the complexity. You simply speak, read, and write your thoughts directly, without thinking about grammar and spelling too much.

It's also visible in sciences and engineering. Mathematical notation is especially notorious: not only every symbol can have multiple meanings, but you're expected to also guess which meaning was intended from other symbols and text around. That's on top of introducing hundreds of made-up words for equally made-up concepts, like a "number", or "monoid in the category of endofunctors".

Finally, it manifests in programming and programming languages. In various ways. For example, there are some people who use APL, K, or J - because it's "easier to read and keep in your head a single line of APL than a 500 loc of equivalent C". If given a chance, they will tell you that something like this is of course very readable and straightforward:

    ⍝ John Conway's "Game of Life".
    life←{↑1 ⍵∨.∧3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵}
You just need to learn a few things first, and that may be hard, but once you do - I'm told - reading and writing code this way becomes effortless, and a thousand times more efficient than writing in C.

Basically, if you're going to be switching languages every year, then yes, there's a difference between having to learn the language for a month rather than six before you can ship something. On the other hand, if you're going to stick with a language for a decade or two, then the long learning process becomes irrelevant, as it's dwarfed by the rest of the time where you actually use the language.

> it still is hard to follow the flow

It may be hard if you're not familiar with the common patterns of using higher-order functions. HOF and lambdas are not GOTO: there's a structure there, it's just richer than the basic set of if/for/while statements. You could call such a structure an FP equivalent of OOP design patterns.

> calls to other functions call back to local lambdas

Yeah, but that's also true for every abstraction, starting with a procedure definition. Also, you don't need lambdas to have this problem, it's enough to register procedure as a signal handler, or register an event handler in some async framework. When you pass a comparator function to `qsort`, you similarly don't know when and how that function will be called, even though it's a named procedure.

To summarize: no matter the language, you can learn it, you can fit all of it in your head, and you can make it readable for you. It requires effort, which is an investment: it might not be worth your while, depending on your circumstances. However, if you encounter a code you don't understand or have trouble with reading, because you didn't invest enough time into learning the language, that's not the code's (or features') fault. Just be honest with yourself and don't blame others for what is a result of your conscious decision.

Also of note: yes, the features often do differ in their complexity, and the differences influence the readability (for lack of a better word). However, to see this and to be able to compare, you have to first learn the features in-depth.

Post reply on HN