Live data from Hacker News

The Hidden Cost of C++

rachelslabnotes.com

51–60 of 66 posts

Re: The Hidden Cost of C++

#51
post #31
post #29

Earlier quoted context omitted.

I am surprised to see that so many programmers still like to reason and guess what the performance of their program is instead of profiling it... And hearing C proposed as an alternative to C++ is mind boggling. I don't want to match malloc/free calls, strcat strings together or realloc pointers. I don't want to declare a bunch o function pointers in a struct and call it OOP. I don't want to use macros because C99 ha…

I propose a lower level than C++ for the kernel, and a higher level for the rest. C++ is simply at the wrong abstraction level. Oh, and I don't want to manually track resources myself, either. But guess what, somebody has to do. And on a game console, that's you. There's not much of an OS to speak of. You did notice I was talking about game development, right? ;)

I've experienced the effects of trying to have the C++ "kernel" and a HLL for the "rest" on a project.

We allowed large parts AI/gameplay (not generally what I would think of as "kernel") to be pushed out of C++ into a HLL, and it was extremely painful bringing it back when the performance began to hurt us.

Re: The Hidden Cost of C++

#52
post #17
post #8

The argument boils down to the fact that C++ can express more in a single line of code than C can. a = func(b,c); .... Is it a function call, a member function call, or is it an anonymous constructor? Are b and c implicitly invoking copy constructors for other classes as part of type coercion? Is that a normal assignment, or an assignment operator? Is there a cast operator involved? If it's such a complicated express…

Second part of my reply... The not-so-hidden cost of C is that even simple things end up being many, many lines of code Yes. If I care about performance, that is a good thing, because I immediately know the cost. >C++ was invented because certain kinds of C programs -- programs that were already being written in C -- were painfully verbose to express and complicated to change That is certainly true, but I think C++ h…

But the amount of code, modulo repetition and redundancy, that you need to look at to understand performance remains the same. You admit that in C you have to understand the performance of a function to understand the performance of any line of code that calls that function. That's just common sense. In C++ you have to understand the performance of functions, member functions, constructors, and destructors. That's more different kinds of things, but it doesn't mean there's more complexity in the program to actually understand.

This is where the C++ problem comes to bear - I have no direct control and knowledge of all classes involved in a particular computation. Yes, I can look them up - but not everybody does. And I'm concerned with building shipping products with a normal team, not some hypothetical team of superstars.

There's no difference in time or difficulty between looking up a C function and looking up a C++ member function, constructor, or destructor. Working on a codebase full of C++ language constructs and acting like only C language constructs matter is passive-aggression and should be treated as a morale problem, not a programming problem. You don't need superstars, just normal programmers who are willing to learn the language features used in the code they're hired to work on. C programmers who are happy to take a job using a different language but refuse to actually learn the language is such a 1990s problem. It shouldn't be tolerated anymore. It was a big problem in the Java community, with predictable results, and resulted in all kinds of ludicrous complaints being leveled against Java (lack of macros was raised many times as a fatal objection to Java -- there were so many things you simply couldn't do in Java because of the lack of macros), but the problem was solved -- people learned how to recognize and not hire those people.

Re: The Hidden Cost of C++

#53
post #47
post #14

Earlier quoted context omitted.

Your counterargument boils down to "use C instead". That is exactly what I am currently advocating. I don't blame C++ for screwing up - I blame it for being an ill-designed language that makes it easy to screw up. Any of the high-level features of C++ are well-implemented in any number of decent languages that don't obfuscate your code and incur horrible link times. And my argument (for game development) is that C++…

No, my counterargument is to use the features of C++ when they help and not when they hurt. I claim that C++ doesn't hurt C programmers. It just brings out their deficiencies in different ways. For instance, embracing features you don't understand and then complaining about the consequences is stupid, and stupid people don't write good code in any language. You understand C++ well enough to know the pros and cons (or…

No, my counterargument is to use the features of C++ when they help and not when they hurt.

That was Stroustrups reasoning: "Only pay the cost when you use it". In retrospect, believe that that's a bad choice for language design, because there's a good chance somebody will use a feature without fully understanding the ramifications it has over the entire code base.

C opts for the opposite and uses annotation to treat certain code segments as "special" and make them faster - "inline", and (in the distant past) "register" come to mind.

(or at least the cons)

I believe I do get the pros as well, at least to some extent. I've been using it since CFront came out ;) And I'd still advocate it for use in a small team (can make it sing.

But gamedev engineering teams are at least 15+ people, with the occasionally less-experienced ones thrown into the mix. C++ is, in a sense, like a professional power tool. It sure can get stuff done, but the wrong person uses it and its a blood bath, and it's not appropriate for single small home repairs. (Gah. Bad analogy, but I can't come up with a better one right now)

This is just bad programming practice on their part. The performance cost of a destructor shouldn't be a surprise to the person who writes it

Possibly. I'd argue that it's hard to always keep all performance ramifications in mind. But let's for a moment say it's indeed simply bad programming practice - the issue that makes this a problem is that my code pays the cost, not the offending code. Which is a rather indirect.

C++ changes often have tendrils all through the system. It is easy to make inadvertent mistakes.

* but it is definitely "decent" in the sense of "adequate.*

It clearly gets the job done, yes. We are shipping games occasionally, after all. I'm looking for better ways to ship games, and I think that abandoning C++ might bring gains.

The second problem with C++ is that it's extremely complicated and takes a long time to learn.

That's what my hidden cost is referring to - C++'s complexity makes it hard to understand. You certainly can write code that performs well in C++, but it is arguably harder to get it right than C.

I like to think there's a better solution than either one hiding somewhere, but I haven't found it yet.

Re: The Hidden Cost of C++

#54
post #52
post #17

Earlier quoted context omitted.

Second part of my reply... The not-so-hidden cost of C is that even simple things end up being many, many lines of code Yes. If I care about performance, that is a good thing, because I immediately know the cost. >C++ was invented because certain kinds of C programs -- programs that were already being written in C -- were painfully verbose to express and complicated to change That is certainly true, but I think C++ h…

But the amount of code, modulo repetition and redundancy, that you need to look at to understand performance remains the same. You admit that in C you have to understand the performance of a function to understand the performance of any line of code that calls that function. That's just common sense. In C++ you have to understand the performance of functions, member functions, constructors, and destructors. That's mo…

There's no difference in time or difficulty between looking up a C function and looking up a C++ member function, constructor, or destructor

There clearly is. In my hypothetical C example, there is one function I need to look up. In the C++ example, there are up to four classes:

* Anonymous constructor class * Class for each in-parameter * Class for the return value.

just normal programmers who are willing to learn the language features used in the code they're hired to work on

The problem is that the set of language features in C++ is huge. The issue is not programmers who don't want to learn, but programmers who haven't learned the whole language yet.

I can't solve that in the hiring process unless I exclusively rely on senior-level programmers. And those are hard to come by...

Re: The Hidden Cost of C++

#55
post #45
post #38

Earlier quoted context omitted.

None of what you've said is in any way specific to C++ APIs can easily lose performance when refactored for correctness or code clarity. Large projects have large project issues!

The difference is that the API can change without visible API changes. If you add a virtual destructor to your class, I won't notice that by looking at the call site. I've just been burdened with additional overhead, without knowing about it. And yes, large projects have large project issues. It is kind of telling that C++ needs an entire tome on large project issues, though... (Lakos, Large Scale C++ Software Design…

The difference is that the API can change without visible API changes.

I don't understand this at all. The performance of a C function can change without any change to the function signature. Even the destructor scenario can happen invisibly in C code for any type that already has a cleanup function. No matter whether the cleanup function is defined as "int myproj_FooCleanup(struct Foo* foo) {...}" or "myproj::Foo::~Foo() {...}", you won't notice implementation changes until runtime.

Re: The Hidden Cost of C++

#56

I fixed a single line of code that drove our embedded processor to 50% cpu - it called 5 ctor/dtors. Changing it to a ref arg with a ref return, and dropped to under 10%. And yes, class defs had to be redeclared, the line of code was unchanged. Very indirect, utterly beyond the original authors comprehension.

Why do you use C++ for an embedded processor?

Re: The Hidden Cost of C++

#57
It always surprises me that some will seek to defend C++ when even its author seems to admit that it is flawed. Many famous programmers have pointed to the language's limitations. People use it because of pragmatism: it has what they need for the APIs they want to use.

If you think C++ is not overly complicated, just what is a protected abstract virtual base pure virtual private destructor and when was the last time you needed one? Tom Cargill

Re: The Hidden Cost of C++

#58
post #51
post #31

Earlier quoted context omitted.

I propose a lower level than C++ for the kernel, and a higher level for the rest. C++ is simply at the wrong abstraction level. Oh, and I don't want to manually track resources myself, either. But guess what, somebody has to do. And on a game console, that's you. There's not much of an OS to speak of. You did notice I was talking about game development, right? ;)

I've experienced the effects of trying to have the C++ "kernel" and a HLL for the "rest" on a project. We allowed large parts AI/gameplay (not generally what I would think of as "kernel") to be pushed out of C++ into a HLL, and it was extremely painful bringing it back when the performance began to hurt us.

You can't by any chance share a bit more about the project, can you?

I'd certainly be interested to hear about this, because I'd love to know what the breaking points were.

Re: The Hidden Cost of C++

#59
post #48
post #34

Earlier quoted context omitted.

" But the underlying "OS" as well as computationally intensive tasks do not benefit from C++ that much, and it causes a lot of collateral damage. " No. C++ has some pretty huge advantages for performance-critical software. Generic programming makes it possible to write extremely succinct, high-performance code. Operator overloading allows the creation of vector and matrix libraries that look like real mathematical ex…

_why C++ is becoming the language of choice in the HPC world._ And yet, the HPC world looks for a new language: http://www.cs.sandia.gov/Conferences/SOS10/presentations/Tue... And a lot of the HPC world still writes FORTRAN or C. (I.e. BLAS, LAPACK, et.al.) But then again, I don't spend that much time in the true HPC world. Maybe I'm missing a trend there. But from the outside, it looks like C++ is not quite what peo…

The HPC world writes a lot of code in FORTRAN because of the library support, and the fact that there's a ton of legacy FORTRAN code that's genuinely hard to rewrite. There isn't much C work going on; the few C libraries that exist are usually wrappers around FORTRAN code.

Re: The Hidden Cost of C++

#60
post #29
post #6

Earlier quoted context omitted.

Pop Quiz: Why should I clutter my brain with these little guessing games about what the compiler is doing? And why should these pop quizzes slow down my group's code reviews? There are, after all, languages out there that do not force this insanity on us. The alternative for performance-critical applications is not Java, but C. C remains surprisingly tough competition after all these years for those rare pieces of so…

I am surprised to see that so many programmers still like to reason and guess what the performance of their program is instead of profiling it... And hearing C proposed as an alternative to C++ is mind boggling. I don't want to match malloc/free calls, strcat strings together or realloc pointers. I don't want to declare a bunch o function pointers in a struct and call it OOP. I don't want to use macros because C99 ha…

> I am surprised to see that so many programmers still like to reason and guess what the performance of their program is instead of profiling it...

Yeah, us old fuddy-duddies. We also like to reason about the correctness of our code while we're constructing it, instead of writing all of it and testing it. Crazy, huh? Like deep correctness, a performant system does not come from sprinkling some tools over at the end; it's an emergent property of attention to detail at every step.

The performance problems a profiler can show you are the easy ones. Hard performance problems come from users, where you can't touch, feel, and measure the code's dynamic behavior. Somewhere out there, in some customers' hands, software you barely remember writing three years ago is crawling along, and the customer is too livid to clearly express what she's doing to make it slow.

Just like debugging a tough correctness bug from the field, you are stuck alternating between deduction and induction. You try to piece together what the user did, and with luck you can reconstruct the bug! Yay, profile it, deduction worked! But I was almost never this lucky. I was left stuck using my bottom-up understanding of what the source code does and how it could have interacted with the user's setup. Identify a possible critical path for this workload, and stare at that motha with a critical eye: "I think you're slow sometimes. But obviously not always. Why? What could make you slow?"

C++ makes this part much, much harder, because even having narrowed it down to a candidate critical path, you can't look at the source code to know (as reliably and quickly as with C) what the hardware is going to do. Notice the qualifiers there (as reliably, as quickly). I'm sure a C++ expert like yourself could rattle off the whole flying circus of default constructors, copy constructors, operator overloads, and destructors that the compiler spits out, but to do so you will need non-local information in a way that you do not for C.

If these problems don't arise in your practice, awesome, good for you. Your marginal user doesn't consider performance problems bugs. That's a great situation to be in, because it lets you focus on features. But it does lead to question of why you are using C++.

> I don't want to match malloc/free calls, strcat strings together or realloc pointers.

If you don't occasionally really need realloc, that's cool, nothing wrong with that, but what kind of resource-intensive software are we talking about, then? It's an important tool in the toolbox when trying to implement data structures that occupy significant fractions of your address space.

Post reply on HN