Live data from Hacker News

Modern C++ gamedev: thoughts and misconceptions

vittorioromeo.info

181–190 of 221 posts

Re: Modern C++ gamedev: thoughts and misconceptions

#181
post #32

Earlier quoted context omitted.

I would say Java, which I suspect is bound to be a bit of an unpopular opinion here (I expect more startup people than enterprise denizens in HN); but the more I think about it, the more sure I'm that it fits the bill: - Dumb: you bet. The inclusion of lambdas has shaken things a little, but usually Java code is straightforward with little space for "cleverness". The counterpoint to this, of course, would be the meme…

The inclusion of lambdas has shaken things a little I'm curious, do you consider lambdas as more or less "dumb"? Because I consider them the dumbest, simplest and maybe best way to do polymorphism. In a way, OOP's whole shtick was about not using them and instead extend stuff with classes.

It's less dumb than usual Java code in the sense that it's less obvious. Java Lambdas are anonymous, inline implementations of single method interfaces (or abstract classes with a single abstract method). In classic Java you would instantiate an explicit object, from an explicitly named interface (anonymous classes were still allowed, but at least the code would have the name of the implemented interface and the overridden method). This made the code more explicit, therefore more cumbersome but also more obvious. I like lambdas because they make the code considerably less cumbersome but only a little less obvious. But they do make the code a little less obvious, and as such, I would say that they make Java less "dumb".

Re: Modern C++ gamedev: thoughts and misconceptions

#182

Earlier quoted context omitted.

If you read carefully, I said use move semantics to implement containers. That includes std::unique_ptr (a container for pointers with a deleter). The point is that you shouldn't be using rvalue ref parameters, std::forward, etc. in most of your code. Even std::move should be fairly rare.

Any time you want to pass a named unique_ptr across an API boundary, you'll need to std::move it

...which you should avoid as much as possible do.

Passing std types across API boundaries is a code smell.

Re: Modern C++ gamedev: thoughts and misconceptions

#183
post #48

Earlier quoted context omitted.

I think you confuse simplicity with overt verbosity. There is no reason simple code can't have higher-level constructs. The interface to them is just likely very domain specific, and you don't start with them. But after you notice you are copying the same sort of code to a third place, you usually notice a pattern, extract that pattern (with no abstract frills attached) to a unique implementation that can be used eve…

"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.

Re: Modern C++ gamedev: thoughts and misconceptions

#184

Earlier quoted context omitted.

> Make your code simple, dumb and verbose all the time This is a frequently encountered argument, and sure, if you look at any single line , it looks very obvious what it does. But I would argue that verbosity and lack of abstraction has severe drawbacks for a programmer's ability to understand the overall codebase , and it is disastrous for long term maintainability. You start out with 20 identical pieces of boilerp…

This is the theorical argument, but in practice when is the last time you encountered 20 identical pieces? DRY is so prevalent that pushing just 2 identical pieces is now rare in my experience. Professionally 99% of my code is used exactly once in one place. I’m not a library or framework developer, I don’t want component by default, I just want to implement a business rule in the most simple, robust and understandab…

DRY is so prevalent that pushing just 2 identical pieces is now rare in my experience.

I want to work where you work.

I've seen literally 4 separate implementations of the same UI component in the last week. It's obvious that they all started out from a common base (e.g. by looking at variable names, function names, etc). However, over time, each component has diverged, as each project that the component was copy-pasted into just made changes willy-nilly to their copy of the component, rather than recognizing that they have a copy of a shared component and refactoring changes upstream or building common abstractions upstream.

Now I've been tasked with doing the refactoring work to make these components DRY, and I can already tell that it's going to be far more work than management has anticipated.

Re: Modern C++ gamedev: thoughts and misconceptions

#185
post #32

Earlier quoted context omitted.

I would say Java, which I suspect is bound to be a bit of an unpopular opinion here (I expect more startup people than enterprise denizens in HN); but the more I think about it, the more sure I'm that it fits the bill: - Dumb: you bet. The inclusion of lambdas has shaken things a little, but usually Java code is straightforward with little space for "cleverness". The counterpoint to this, of course, would be the meme…

> Fast: also yes. Usually about 2x or 3x the run time of C/C++ code, some times even less. not commenting on the Java part as I believe it's usually faster than that (though not so sure when you see the years of hoops that Minecraft java had to go through to stop being so damn slow all the time...) , but it's kinda frustrating to be fighting for microseconds almost daily and then hear people saying that 2x slower is…

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? This is the best part - over 90% of the memory allocation is not needed at all. Most of the memory is probably allocated to make the life of the developers easier.

HFT is as high demanding as games and it makes use of Java, however I think that Java developers with such skills rather have a HFT salary than what game devs earn on average.

Re: Modern C++ gamedev: thoughts and misconceptions

#186

Earlier quoted context omitted.

I'm a C++ developer who occasionally writes Rust. The experience of writing new code in one is very, very similar to the experience of writing new code in the other, right down to the compile times. The lifetime analysis in Rust is nice and pretty far ahead of what static analyzers can do in C++, but Rust Generics are a pretty weak approximation to Templates. Rust has better Browser integration, C++ has Qt. One imagi…

As someone who built a career in C++ I like that Rust's generics are a poor approximation of templates(and that includes having worked with some of the modern C++ features). I have months of my life I've lost to the increased compile times from Boost on the applications I've worked on. C++ also makes it way too easy to reach for shared_ptr instead of unique_ptr leading to all sorts of unfortunate things. Rust makes t…

Right now Rust eco-system still isn't as mature as C++ in what concerns integration with Java and .NET, and GPGPU programming. The domains I care about.

However with the support of companies like Microsoft, Rust will eventually get there.

By the way BUILD 2020 will have Rust sessions.

Re: Modern C++ gamedev: thoughts and misconceptions

#188
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.

Yes, this very much :)

Re: Modern C++ gamedev: thoughts and misconceptions

#189
post #16

Earlier quoted context omitted.

C++ fold expressions, the main C++ feature the article covers, are simple and dumb (at least, enough to use them) but not verbose, and definitely harder to get wrong than a much more verbose for loop.

I just fixed a segfault the other day because one of our new hires fresh from college is eager on using modern c++ and didn't put parentheses at the correct place in his fold expression.

It sounds like an interesting bug, can you elaborate? On the surface it sounds like your new hire merely used fold expressions to call functions and operators that were already treacherous on their own.

Re: Modern C++ gamedev: thoughts and misconceptions

#190
post #185

Earlier quoted context omitted.

> Fast: also yes. Usually about 2x or 3x the run time of C/C++ code, some times even less. not commenting on the Java part as I believe it's usually faster than that (though not so sure when you see the years of hoops that Minecraft java had to go through to stop being so damn slow all the time...) , but it's kinda frustrating to be fighting for microseconds almost daily and then hear people saying that 2x slower is…

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 would attempt the same operation, and the first thread wins. This approach reduces the likelyhood of a GC ruining the timings. Funny story.

My bachelor's thesis involved writing a software in Java that would manage dozens or hundreds of millions of small objects. These objects were all instances of the same class; the contained only three ints. It was very slow, and especially in an OOM situation the GC would work for more than a minute before finally giving up. I changed the software to use SOA instaed of AOS - moving from a huge array of these objects to three int[] arrays. Since ints aren't boxed, that left me with only 3 objects instead of many millions. The code was uglier for it, but the performance was another world. Unfortunately, such a change is not practical if you have many classes.

That was 5 years ago with Java 8. Disclaimer: I haven't followed Java since then. I know next to nothing about it.

Post reply on HN