6 ms·
The hidden cost of C++ (2009)
- jon6 14y agoI don't necessarily disagree with this assessment but you can easily create functionality in C that requires looking at multiple source files to understand whats going on. x = foo(bar(), baz()); Now you have to look at the definitions for bar and baz to understand the cost of this line. I guess this is the trade-off with using a high level language. Expressivity vs transparency.
- mpyne 14y agoThis page gives another "nice" demonstration of C (in actual usage, not an obfuscated code contest): http://oldhome.schmorp.de/marc/bournegol.html http://oldhome.schmorp.de/marc/bournegol.html What's especially nice is that TRUE is defined as -1 in that source, not 1, which could easily confuse someone who isn't intimately familiar with C's boolean operators and conditional expressions (since something like if((a < b) == TRUE) { ... } would actually be incorrect). Even with that in mind, it would still be nice to have a "safer to use" systems language than C++ generally available. Perhaps Go or D can fill that role (though good luck making that happen for game development on Windows...)
- pjmlp 14y agoFor many years that language for me was Turbo Pascal, but then it faded away. :(
- heretohelp 14y ago>Perhaps Go or D can fill that role Aha! A question I can answer. This one will be easy: No and No. In fact, I can go one stronger than that. Never and never (although they really hoped). Go is a general-purpose language, it competes more close with Java and Python, but mostly Python and Ruby. D is just in an awkward place that has been occupied by Java and C#. Neither are even remotely viable for serious systems work, although they'd work fine for network services.
- BudVVeezer 14y agoAwesome! Another "I don't understand writing good code in language X, thus that language has 'hidden' deficiencies." post. You can write non-performant code in any language you'd like, and obscure it in non-trivial ways. That's not the fault of the language.
- BudVVeezer 14y agoLest I come across as grousing without contributing to the discussion, let's take a peek at the author's main point on hidden costs. Most of the argument revolves around objects. There are two ways you can run into "hidden" surprises with objects in C++ that the author is pointing out. One involves failing to use the language features given, the other involves writing some seriously odd code. class C { public: /*explicit*/ C( int ); // Adding explicit avoids hidden costs // This combination (or something like it) is lethal. C( int, double ); operator bool() const; }; So for the author's code to have hidden performance concerns, they would need a constructor taking two parameters of the proper type and an automatic conversion operator that converts to a type assignable as their result. Basically, the stars have to align right and you have to knowingly write some dangerous code. Don't get me wrong, you can hide costs pretty easily in C++ and write some atrocious code. But usually this issue is alleviated by following basic best practices. The hard part is knowing what those best practices are.
- strlen 14y agoMaking the copy constructor and operator= private (see boost::noncopyable to take care some of that boilerplate) takes care of some of the other hidden costs. I do agree that C++ is a complex and hodgepodge language, but I am not sure there are acceptable alternatives yet. It would be great if JVM had native support for value types, i.e., a way to use manual memory management, bypass bounds checks, or call native code without incurring serialization costs. Yes, I am aware that C# does this (and I like C# and F# a great deal as languages), but a) I am not deploying Windows in production b) Mono is not yet a viable high performance server side platform (it does look promising for desktop and mobile application or for simpler ASP.NET webapps). C is a beautiful and simple language (one I have strong affinity for) but manually implementing vtables is a bit painful (see a large pure C project for an example of that), nor is there any support for type-safe generic programming (which is an issue I have with Go as well -- even though I fully understand their reasons for omitting generics).
- dude_abides 14y agoThe same underlying point can be made in such contrasting styles: Linus ( http://harmful.cat-v.org/software/c++/linus http://harmful.cat-v.org/software/c++/linus ) vs the OP.
- tsahyt 14y agoStill they're both effectively right about it. "Object oriented niceness" comes at a cost. With C++ it might be smaller than in dynamic languages like Python, where things like function call overhead can be ridiculously big, but it's still there.
- zwieback 14y agoI think they are both wrong about it. What the argument boils down to is that the limitations of C prevent you from using things that might lead you astray. That's not an argument for or against C++ it's just an argument against large languages in general and an argument for programmer discipline in specific. It might work for Linus if he reimplements C++ features in a better way but it does not help all users and doesn't help all the time. Do we honestly believe a beginning programmer will be better off reimplementing std::vector or just using a fixed array instead? If I remember correctly somewhere further down in that particular Linus rant he was saying that you can look at a call site and tell what's going on, the same argument the poster here is making, but do we honestly believe Linus never uses function pointers? And the argument about the name of the function giving us a rough estimate of the overhead does not sound valid to me. As a C programmer and former C++ programmer I can see a valid argument hidden in these types of posts but I think we'd be better off with a little less attitude and a little more useful guidelines.
- gte910h 14y agoI think this IS C++ specific. ObjectiveC has a much smaller call site complexity penalty.
- JoeAltmaier 14y ago
- halayli 14y agoAbstraction in general comes at a cost.
- tsahyt 14y agoObviously, yes. One can't expect jumps across multiple levels of libraries, wrappers and APIs to be free of cost. That's what Carmack referred to as "20 layers of crap". He's effectively right about it. On the other hand we can't reinvent the wheel everything we write a line of code. One of the most important aspects of balancing productivity with performance is knowing which parts of code are crucial to performance and should be written with that in mind. That's one of the toughest parts as well. Usually one is better off profiling than guessing but I believe an educated guess can go a long way nevertheless.
- IsTom 14y agoThat's true and the thing with C++ is that its philosophy is "if you don't use a feature, you're not getting performance hit associated with it". Be it anonymous functions or virtual calls.
- lamebrain 14y agoThis also works as an argument against basically any language more complicated than C, which -- since we're not all writing everything in C all the time -- should suggest that although such languages may have "hidden costs", they also bear significant benefits.
- cjensen 14y agoSlapping an "explicit" modifier on all your constructors eliminates what the author is complaining about.
- cobrausn 14y agoI really wish 'explicit' was default and the keyword was 'implicit'.
- nostrademons 14y agoWith modern optimizing compilers and CPU architectures, you can't really predict the cost of code merely by looking at it anyways. Not in any language. Will that function call be inlined? Does it have side-effects? Are the arguments constant, so that it might even be evaluated at compile-time? Can it be hoisted out of a loop? Do its pointer args alias, preventing many of these operations? Is it big enough to blow the cache, or will it all fit in L1 and benefit from really fast memory accesses? Can branch-prediction operate effectively on its loops, or does it have an unpredictable pattern that will flush the pipeline many times? I've heard that the best way to get your program to run fast is to get it into a compiler benchmark suite, so that compiler-writers account for it when writing optimizations. Failing that, it's all about profiling so you can measure the actual cost rather than relying on what you think you know about the programming language.
- fauigerzigerk 14y agoThese are good points, but I don't think it relieves you of having to know whether your making a virtual function call or not, or wether you're passing an argument by value or by reference. You do have to know that, and in C++ you cannot know that by looking at the call site. In C and in many other languages you can.
- eridius 14y agoIn C there's nothing stopping the function you're calling from turning around and invoking dynamic dispatch. As a trivial example, objc_msgSend(). This is a C function, but it's also the entry point for objective-C's message sending (e.g. dynamic dispatch). Basically, what I'm trying to say is, focusing on the cost of the function call itself is useless if you don't know the cost of the function implementation.
- fauigerzigerk 14y agoAbsolutely, but to learn more about the implementation you have to look at the function's code. Every line of that code poses the same problem, so it's recursive down to every last expression.
- VikingCoder 14y agoThe days when you can reason about performance by looking at function signatures are, in my opinion, long gone. I can count on one hand the number of times that I thought that changing the function signature of a few methods was going to impact whole application performance. Every time, it was in a low-level function that was called all over the place. Or, more to the point, I dug into function signatures when evidence pointed me there. I can't even begin to list all of the other problems I worry about that actually do impact whole application performance on a regular basis.
- kqr2 14y agoNote: post is from 2009. She also has a followup where she explores the "pressure points" of writing games in C++: http://www.rachelslabnotes.com/2009/11/there-are-never-enough-render-engines/ http://www.rachelslabnotes.com/2009/11/there-are-never-enoug...
- 16s 14y agoI use C++ daily for systems level programming and I love it. If I could only have one programming language it would be C++. I can write anything in it and I actually enjoy doing so. Maybe I'm weird or something, but I know a lot of other guys who feel this way too. And, I know some other guys who do hard core embedded C programming and they are migrating to C++. They love it compared to C and can't wait until every line of their C code has been reimplemented in C++. C++ will be around for decades to come and many folks actually enjoy writing it, they just don't advertise that fact.
- alexchamberlain 14y agoThere's 2 of us!?!
- Shorel 14y agoAdd me to the club. Except that I also enjoy some Lisp from time to time.
- dkarl 14y agoDecades might be right. I can't think of a compelling reason for anyone to learn C++ today, but having put in the time to learn it reasonably well, I won't be surprised if I find myself still using it occasionally twenty years from now.
- mike-cardwell 14y agoI started learning C and C++ about three months ago. My reasoning is, they're used all over the place. My operating system is written using C and nearly all the applications I use are too. I want to be able to modify the programs I use, and I want to be able to write native applications that run quickly. Those are my motivations. And I haven't been this happy learning a language for years.
- lelele 14y ago"I started learning C and C++ about three months ago. My reasoning is, they're used all over the place. My operating system is written using C..." Your operating system is written in C. Why learn C++? The return of investment of learning just C is much much higher than learning C++. Been there, done that.
- eridius 14y agoI'm disappointed. I expected this to be a post along the lines of Ridiculous Fish's two posts on C++ features that you pay for even if you don't use: 1. http://ridiculousfish.com/blog/posts/i-didnt-order-that-so-why-is-it-on-my-bill-episode-1.html http://ridiculousfish.com/blog/posts/i-didnt-order-that-so-w... 2. http://ridiculousfish.com/blog/posts/i-didnt-order-that-so-why-is-it-on-my-bill-episode-2.html http://ridiculousfish.com/blog/posts/i-didnt-order-that-so-w... Thankfully one of C++11's requirements was to not introduce any new functionality that had penalties even if you aren't using it. Too bad that wasn't a requirement for the original design of the language.
- JoeAltmaier 14y agoWhile that was informative, its not really C++ specific. The runtime example was library routines.
- eridius 14y agoWhat do you mean, it's not C++ specific? The runtime example is very explicitly fallout from a requirement of the C++ specification, which affects C++ extern inline functions.
- JoeAltmaier 14y agoWrong example - read the 2nd link.
- eridius 14y agoThe C++ spec includes the standard library. The COW optimization is a common one (although perhaps not anymore with C++11, see other comments). The C++ spec imposes certain requirements on the std::string interface that are the source of the problem documented in that link. In fact, the exact requirements of the C++ spec that cause the problem are talked about, along with an example of what a simple solution could have been (if it had been considered when C++ was being standardized). So saying it's not C++ because it's standard library is at best a misunderstanding, at worst it's disingenuous. The C++ spec is the cause of this fundamental problem with any attempt at doing COW optimization of std::string.
- malkia 14y agoin 1999 I was a total C++ dude. I had to work that year on a port of metal gear solid for PC. I was surprised to see such well written C code by the konami developers, with nice oo system that had certain tcl element to it. There were only comments in japanese but that did not stopped us from understanding how it worked.
- justinhj 14y agoExactly. I started working in video games programming in '93 when C was considered high level, and most games were written in assembler. C has an elegant simplicity about it that both enables you to implement the high level features in the way you want to, without being able to obfuscate your work with hidden or automatically generated functionality. Whenever I've worked on all C codebases I've always had less pain and more productivity than C++.
- gte910h 14y agoObject oriented C is a great paradigm when done right.
- pjmlp 14y agoProblem is that 99% of the developers that work in the industry usually do it wrong.
- gte910h 14y agoI'd say the number of people who do object oriented C right is as high or higher than the people who do C++ right, for a given set of people. It's just simpler, with fewer leaky abstractions.
- LiveTheDream 14y agoCan we get a [2009] in the headline?
- lelele 14y agoFor me, the hidden cost of C++ was the mental overhead of programming in it. I had to be constantly alert about the many many ramifications of almost every line I wrote.