Less is exponentially more (2012) (commandcenter.blogspot.de)
I was asked a few weeks ago, "What was the biggest surprise you encountered rolling out Go?" I knew the answer instantly: Although we expected C++ programmers to see Go as an alternative, instead most Go programmers come from languages like Python and Ruby. Very few come from C++.
281 comments
[ 5.0 ms ] story [ 292 ms ] threadIt probably doesn't scratch their itch.
The issue, then, is that Go's success would contradict their world view."
This, "they can't handle how awesome it is" is kind of a fun rationale and strikes me as plausible, but it would be more interesting to me to hear from some of the stellar c++ programmers at google as to why they aren't interested in switching.
C++ was the first language I really invested in mastering during and after college - it was like, "all I need to do is read these 5 books about how to avoid the pitfalls and use all the powerful tools, and it's amazing!" What really changed my mind was trying other languages (first python) and seeing how immediately productive I could be without so much as skimming through the "dive into python" website. So specifically, I'd be interested in hearing something from an expert C++ programmer who has really given go a try and decided it's not their cup of tea.
This is partially why you picked up Python so easily. It's one thing to approach a language like Python as your first, but if you took the dive and learned c/c++ prior, everything else is going to be much easier to grok.
That said, I can report on what I prefer right now, knowing what I already know (having spent 4 years programming java professionally as well) - and I truly prefer a more functional approach that comes a lot more easily in languages that support closures and first class functions. It also strikes me that many of the best practices in java / c++ are basically moving towards more functional programming (prefer composition to inheritance, make objects immutable by default, interfaces over classes when possible, dependency injection / referential transparency and parameterizing methods by interfaces e.g functions).
Go drops that control totally in favour of it's inbuilt garbage collector which the Go devs think they can just get right. That seems unlikely (the current implementation is apparently quite bad stop-the-world implementation).
Another issue that strikes me is library building. Afaik Go doesn't produce object that can be linked against by non-go stuff. C does this, it has a ABI.
This means I can write one library in C/C++ (and apparently Rust) and then have wrappers for just about every other programming language in existence. (Although C++ can make this painful with things like exceptions http://250bpm.com/blog:4 ).
It might be that Go's interfaces make it really useful for making Go libraries in, but some libraries need to be language agnostic as much as possible.
Many of the things Go initially solved over C++ are being chipped away too. I love reflection, it would be very useful for games, serialization and so on. C++ doesn't have it but there is a standards working group looking at it now, so we could see it in either C++14 in a year, or C++17 (probably with implementations before then). C++11 got threads and so on and there is a working group doing transactional memory, more threading stuff, networking and so on. So we could see something like Gorutines and Channels but still have access to low level things like raw memory barriers. C++ tooling is set to explode with what the clang people are up to.
Go seems great, but it does seem focused in the 'business' kind of domain. Maybe future versions could address some of the issues like the GC (either fixing it so it does meet the performance requirements, or allowing custom memory options, C# has the unsafe keyword for example).
EDIT: I note that Go might provide a package "unsafe" that could allow for some things like a custom GC but apparently would be hard to implement.
I have worked for a company who wrote a state-of-the-art 3D PC gaming engine in C#.
Being garbage collected doesn't remove the ability to manage memory. It just removes the need to call Malloc directly.
How does it compare to Cry Engine, Unreal Engine, Frostbite, ...?
Because these are the state of the art gaming engines these days.
It was C# from the ground up. Scripting was provided via other .Net languages (Python in the case of the UI team).
[1] http://en.wikipedia.org/wiki/Command_%26_Conquer_(2013_video...
Which game's engine was in C#? Project MyWorld?
I realise that there are no doubt a number of custom C++ engines out there with embedded scripting languages but push for multi-platform mobile games has caused an huge shift towards Unity.
Maybe I'm moving in the wrong circled here — but anecdotally all the people I know making iOS & Android games are developing in Unity.
And I don't doubt that alot of devs use Unity, it's most likely the most popular game engine. But it's still a C++ project, despite the languages used to script game events...
When the engine underneath is done in C# as well I will take that argument. So far, it would be the same that saying that most console games are done in UnrealScript.
I know many iOS game developers and none of them use Objective-C any more.
(in fact I only ever knew one)
Well, for shitty games maybe it is true, shovelware aplenty on iOS anyway.
But for the part of the market that actually has a profit (not just revenue) C# is not that dominant.
In terms of profit, the most profitable games probably still rely on C++.
Also most engines (including Unity) are made in C or C++, they sorta abstract the memory management for the game author, but they still do a lot of manual fiddling themselves, XNA for example (that allow you to write C# games directly to the hardware without a C++ engine) is notorious for bigger games having memory issues.
Also 2D "retina" games use so much absurd amounts of memory, that they are almost impossible to do purely in high-level languages, you need some C or C++ somewhere to handle them, at least texture loading, otherwise you end with loading times so big that people want to suicide.
Loading times have been an issue since game consoles moved away from cartridges.
On top of this, things like bit-packing and tagged-pointer type things can allow you to save memory, allowing you to fit more stuff into cachelines more efficiently, giving even more speedups.
This is the same guy who said you don't need to know what I know (re: endianness) because you will never write a compiler. Consummate narcissism.
Narcissism: I am the most beautiful of all.
Elitism: I am more beautiful than you.
However, he has a history of being insulting towards people who want to use different paradigms. So if you're going to bring that line up with anyone, bring it up with Rob Pike himself.
I don't know what qualifies as an expert, but as someone who is using C++ and Java (and did look at Go):
- If I want a garbage collected language that is reasonably fast and safe, I prefer Java over Go, since there are many high-quality libraries available, there are good IDEs, it's easy to instrument the JVM (heck, I can even debug a remote application running in Tomcat in my IDE), and has a good central repository and package manger (JVM). Go is hardly more expressive than Java, so if I am looking for a replacement, it will probably be Kotlin or Scala.
- There are applications where I want manual memory management, auto-vectorization, real generics (templates), etc. Go has none of these features.
In other words: Go does not offer me any advantages over Java or C++. At the same time, moving from Java to Go would require me to sacrifice a lot of well-developed and reliable tools and libraries. I know that someone is going to mention Goroutines and channels. There are great concurrency options for Java as well, e.g. Akka, which implements actors, futures, a scheduler, remoting, and clustering. In comparison Go's concurrency offering is quite pale. Sure, you could implement something like Akka on top of Go, but it currently does not exist (except for a binding against Erlang's C node functionality).
Writing in Go isn't as strict or structured as Java which I really enjoy. I used to write a lot of C++ and although I was never a pro, I did really used to enjoy programming in it. Go is certainly a breath of fresh air to develop in in comparison and I find that I can write more concisely and if anything performance seems to improve as I am not making trivial mistakes that "powerful" languages like C++ allow me to repeatedly make. KISS.
As always, it's horses for courses.
Have you tried a modern, expressive, strongly typed functional language like Scala or Haskell? I can well believe that go would be an improvement over Java, but Java's not exactly state of the art these days.
With regards to security issues, I was under the impression that since oracle took it over, Java has had prevalent issues that have just been ignored by Oracle. Quick search seems to agree..
I have played with Haskell and really enjoyed the language. Although imperative languages are my bread and butter it certainly gave me a different approach to programming, primarily stepping away from an OO design and love of recursion!
Haskell is a lovely language and everyone should dabble in it for a while, for that very reason: because it makes you look at programming differently.
Nor was it when it was created. It was born outdated (just like go!).
There was some recent discussion about the "Edward C++ Hands" article. [1] And that discussion summarizes neatly the issues I have with C++. Yes, I get that it is a powerful multi-paradigm language. Yes, I get that it will take time to master.
But should this language (or any language; I'm looking at you Javascript) have so many hotly-debated dark corners and pitfalls? It is an enormous undertaking to just figure out what the best practices are. And it is then a further enormous undertaking to get the rest of your team on-board.
[1] https://news.ycombinator.com/item?id=6414162
I am not a C++ expert but I have programmed a fairly amount of C++ code so I will give you my two cents.
I use C++ because a blend of three things:
* Performance,
* Abstraction and
* Portability.
If I would care just in a subset of that tuple I probably will code in something else.
For instance, if for some project performance is not an issue, I will probably use a higher level language like Python or Scheme. If I am feeling that Abstraction is not as important as performance and portability I will use C.
When I care about the three of them I feel there are not too many options.
* Performance
* Portability
* Direct API access (D3D, OpenGL, console specific APIs)
* Large legacy codebases
* Control over memory management
Go doesn't really address all these areas adequately at the moment from what I've seen. For me personally, for those problem domains where the above are not a concern I find other languages more compelling than Go - Haskell, F#, even C#.
* The long C++ build times he was complaining about are mostly gone due to distributed builds. http://google-engtools.blogspot.com/2011/09/build-in-cloud-d... Throwing resources at the problem isn't ideal, but it does work.
* Google has a lot of C++ library code, including client libraries for things like Bigtable. Go's Google-specific libraries are a work in progress.
* For serving systems, I care more about machine efficiency and latency for than about development time. I'm still skeptical of those properties in Go. Obviously the compiler (and my comfort with it) will improve over time. So will the garbage collector, to a point. It will always operate on one large heap like Java's. People say Java's GC works fine, but they spend a lot of time tuning it and then quote pause times that don't thrill me. I've seen a lot of problems caused by bad tuning parameters, like (for example) Java heap sizes that exceed the size of the container it's running in. And relatively hard-to-diagnose and slow-to-recover GC death spirals because the defaults suck: Java just bogs down in situations where a C++ binary would dump a heap sample, crash, and get restarted. So I'd be more comfortable with a system like Rust's: many smaller heaps, language enforcement of ownership rules when transferring between its equivalent of goroutines.
Now for internal tools, where speed of development is more important, I wish I could magically switch everything over to Go instantly. Some of that stuff is in Python. Python's fragile in an always-refactored large codebase without 100% unit test coverage. The library situation is worse than Go's (few Python-specific libraries, and I hate SWIG). And while performance is less important for internal tools, Python's horrible single-threaded performance and GIL are a real pain. And finally, using Go for internal tools might eventually give me the comfort I need to start using it for more serving systems.
I'm a Google C++/Python programmer who has (mostly) switched to Go for new development. Rob's statements about C++/go compilation performance are still relatively correct. The client libraries are sufficient for many, but not all projects.
I think what most people don't appreciate is how cleverly the Go team at Google established a reasonable migration path for internal developers. Some systems have migrated far more quickly. hopefully, we'll see some papers describing the migration at some point.
Now, build times are not a major loss of productivity for me. In fairness, I don't work on the same system he was working on, and presumably not the same as you either.
I started a year after that time.
My perspective is similar. I do a bit of Java, C++ and Python, and recently wrote a ~1K LOC backend in Go. I figured I'd share it in case someone finds it interesting.
For low-level infrastructure projects that don't have very complicated business logic (e.g. caching systems, gateways between different RPC systems, etc.) but which run in many machines and must handle many requests per second, I'm sticking with C++. It's sometimes painful to troubleshoot race conditions around resource destruction issues, given that I use lots of async calls and threads, but still ... I don't think I'd feel comfortable investing significant efforts building this kind of systems in Go or even Java. That said, I'm trying to gradually migrate away from callbacks spaghetti and data sharing between threads towards ... specialized threads and message passing, a model far more similar to Go's. But I prefer C++ over Go and Java because it feels more predictable and, barring bugs, seems to have a lower operational cost. I don't want to imagine things like Bigtable or Google's other storage systems written in anything other than C++.
For higher-level backends with more business logic but which still must handle many requests per second, I lean towards Java. I feel that Java brings a few headaches for the production engineers that for some reason happen less in C++, such as having to tune the GC for performance and latency. Systems in C++ feel significantly more predictable, from my production perspective. But I'm willing to lose that predictability and switch to Java for the gains for the development team. I'm not sure I would be ready to switch to Go: I perceive the state of internal libraries on Go as trailing significantly behind those in Java. I guess this may change (or my perception may even be already dated).
Finally, for internal servers with little load, I'd already pick Go over Python. I come from a strong Scheme background and originally really liked Python, a very nice subset of Scheme. However, I'm coming to find projects in Python relatively hard to maintain. :-/ I feel that when Python projects hit a certain size (when a program reaches something like ~20 non-trivial classes, with some inheritance or interfaces, something like that), it becomes hard for new comers to extend it successfully. It may be just me, but I find that the lack of a canonical way to do things like interfaces means everyone has their own adhoc way to do this and ... things just get messy, or at least more messy, faster, than they do in the other 3 Google languages. It could also be the lack of type checks at compile time, I'm not sure. But I digress, all I meant to say is that I think Go may actually make things a lot better than Python in this regard, so I'm starting to use it in this area.
You'd know more about Java's strengths than I would. I haven't really touched it since we parted teams. I just remember production pain...
I'm sure the Go library situation will improve, and we can nudge that along as we write internal tools. I'll definitely start my next one in Go. I might even translate my last one to Go sometime.
However, I recently started using Python and I absolutely love it. Using python, I can usually whip up a proof of concept within minutes because things just work. I wrote a OCR program using a mix of OpenCV and Tesseract in Python, and I was able to get a proof of concept up in about an hour. Of course, the performance isn't nearly what I want it to be (on the order of seconds, which is too slow for my application), but the fact I could get something working so quickly is why I love Python so much.
No it won't! I'm excited about Go. What I've read about it makes it look like a language I would love to work in, some day. However, I don't think the problems I'm solving now are the problems Go is good at solving. The programs I'm writing run on one machine with restricted memory, and they need to be highly, highly performant. The execution time is measured in tens of milliseconds, and during that time we do a lot mathematics and processing. SIMD is our close, beloved friend. In that context, I don't think Go is an appropriate language, due to its garbage collector, its lack of precise control over where objects go in memory, and the overhead of method calls. But if I ever write code similar to that written by Google, C++ would be a terrible choice.
I was all on board with what he was saying until that last little jab. I'm not migrating to Go because I have problems that Go doesn't set out to solve, but I'm not threatened by Go, because it's just another tool. Having more high-quality, carefully-designed tools is never a bad thing, and I can't imagine ever being threatened by a new tool's success.
Honestly, this smacks of more divisive bullshit. Pythonistas vs Rubyists, VIM vs Emacs, and now, Go vs C++. Blurgh.
The main thing is that the garbage collector is a problem in time-constrained and memory-constrained environments. I can't afford to wait to clean up my large data set until the GC decides to, and I can't afford to wait the 100ms that the GC may take. Or, more accurately, I might be able to, but I just don't know, and that lack of certainty means that a GC language is not an option for me.
But that's not to say that Go suxxors! Different solutions to different problems. I'm just saying why I won't be using Go to work on the project I'm on now.
The thing with Go is that it is (was?) marketed as a system's programming language. Go might work as a replacement for Java, but Java is not for system programming.
Whoever decided to say Go was capable of it either has no idea what systems programming means or was being deceitful. Go can not replace C++; these languages don't solve the same problems.
This topic/article should have been re-titled, "Rob Pike on Why Go continues to be incorrectly marketed to systems programmers".
Go is not a systems programming language, since it gives barely a passing nod to control. Thus, it does not fall in the same core domains of C++ or C.
But they're not C++. As soon as you tie the whole language to a garbage-collector and leave out any real mechanism for metaprogramming or even simple generics, you've lost me.
Pure text-based lexical macros like templates are a weapon of last-resort for language design... but it's not an optional one. Dynamic-typed languages cheat by offering a simple "exec" statement/function. Static languages have a religious objection to offering a first-party preprocessor, because they have the hubris to believe they can solve every possible problem ever within their language.
Nobody is that good at programming language design. Not Pike, not Gosling, not Ritchie, not anybody. The difference is that Ritchie's team knew that, and didn't try and pretend that every single thing could be easily and performantly expressed in their language, and made the hackish ugly macro system to solve the edge cases... and it worked.
"templates, a powerful macro system"
I really like Rust, but I haven't been paying attention for a month or so; did something change? Templates? And the macro system was...oddly limited when I tried fooling with it.
What do you use template metaprogramming for, except to compensate C++'s flaws?
(I agree with you on automatic GC and lack of generics, but not on C++'s template model in general and especially not template metaprogramming. TMP is just the most horrible, hackish way of scripting your compiler, and I've rarely, if ever found a use for it.)
The article's argument, however, is that C++ programmers are wrong to presume that those things are required for systems programming.
Interesting.
It's fine to think of GC as "fast enough" in 2013, but that's when you're working on things were speed/space isn't scarce. Go might work out for Google, since their "systems" comprise of tens of thousands of computers, where reliability and maintainability are more important than latency. For the rest of us C++ coders, we'll probably won't be able to replace C++ with Go for the tasks where we need to do systems programming, simply because we on things that require us to be control freaks.
Quite frankly, this post by Rob Pike saddened me, because it seemed like he was desperately trying to counter the Go criticism with a not very well thought out rant.
I've always though that, other than objective measurements of binary code performance, whether or not you think a programming language is good is almost entirely determined by its syntax and feature set. I feel no need to go around the internet all day proclaiming my programming language of choice to be the best and/or others to be inferior.
This reminds me of that link I saw on here a while ago titled "Why Go? Use Racket!". Personally, my answer would be: because I find 9000 brackets in a simple program to be poorly readable. However, I respect anyone who disagrees and thinks the opposite. If it allows them to make great software and have fun doing it: by all means go for it!
You apparently thought the write-up was somehow overly condescending to C++ programmers (I assume), while I personally thought it was the complete opposite.
If Rob Pike was doing things in C++ that Go could also solve, that means he could've done them in C# or in Haskell too, which means he shouldn't have been doing them in C++ in the first place. (Strousup explains why in his recent GN keynote if you doubt that)
Of course solving that problem by inventing a new interesting language without any of the (psychologic) baggage those other languages is awesome. It seems to be rather succeful, but it's naieve to think that it would attract C++ programmers, there's just nothing in there for them. The C++ programmers who are looking for change have more to hope for in for example Rust.
All of those foist garbage collection on you. Many of them find text-based macros such as C++'s template engine morally offensive and so they don't include that feature.
If you want a statically-typed Python, then Scala and C# and the like will serve your needs nicely.
If you want a modernized C++... it still doesn't exist. Rust looks promising, but that's not exactly mature technology.
If this is true, isn't it obvious why? Small projects do not need Go, while big teams with big projects will always be extremely slow to adopt anything new.
C++ covers many domains and programming styles really well. Just because it doesn't cover some as well as some other language, it doesn't mean C++ as a whole is a lost cause. This is true no matter how many domain experts and language advocates attack it. It's C++s huge scope that opens it up to attacks from every corner in the first place.
Frankly I'm getting tired of reading articles from people who think they can proclaim "what C++ is about" any more than I can proclaim "what Go is about" or "what Python is about". Even Bjarne himself admits he doesn't know all the ways in which people use C++, and that's how he likes it.
In c++, I like the predictable destructor model of memory cleanup, and am willing to pay the manual error checking price (too scared to write exception safe code in c++). But I like to put as much complex logic in python code, due to its nice exception handling and GC.
If GO had a more flexible exception model, which by the way does not require forward jumping try/catch constructs, making it easier for people to write 'crash only' error handling without boiler plate, I might consider it. But for me, it's currently typecast as a firmly middle of the road feature set.
I can understand not going the full Java/C++-level overhead (although Python is a great example of how that doesn't need to be so tedious in practice) but it still amazes me that simply importing something you don't use is a fatal compiler error but the classic "res, _ = something()" responsibility shirk you see all over the Go world doesn't even get a warning.
Maybe Go 2.0 could make the compiler simply do the equivalent of inserting an `if err != nil { panic("Unhandled error at FILE:LINE") }` block after any statement which can return an error and doesn't already have a check. That'd satisfy the low-overhead, predictable flow-control crowd while making the language much safer for large systems in practice.
(n.b.: lest that seem like too harsh a condemnation, I actually rather like Go as a highly appealing alternative to C: the fact that they got so many things right — gofmt alone deserves a medal — makes the minimal error handling feel like a surprising oversight.)
(That would be my first choice if writing a web app is infeasible, but it's been a while since I've followed the project.)
Kind of silly he drew up his language based on one Google need and thinks everyone using C++ should just jump aboard, though. He acts like he studied why people were writing in C++ and took their use cases into account instead of just his own. Kind of a stereotypical engineer who writes an app for themselves that utterly fails in the consumer market because it is written by coders for coders with weird controls.
Since far better languages than Go have existed for many years, and those have failed so far to attract many C++ programmers, I just think this is never going to happen until C++ programmers themselves die out.
Sure there are bindings, but they are often incomplete and not quite stable.
I will switch the day a language allows me to transparently call my existing C++ library, without having to spend time writing and debugging swig/boost::python/whatever wrappers.
To quote an old cliche, right tool for the job.
GC is all about using `malloc/new` without thinking `free/delete`. With modern C and C++ there are a lot of mechanisms for that (passing values, auto_ptr and shared_ptr for example). In many cases a C++ programmer doesn't need to think about `free/delete` either, and in some cases the non-determinism of GC decreases the productivity too.
The point being that in any discussion about new C++ features the central point always tends to devolve to:
What is the cost to me if I don't use this feature in my programs?
If I don't use exceptions, I don't pay for them. If I don't use virtual member functions, I don't pay for them. If I don't use RTTI, I don't pay for it.
In other words: If you want/expect C++ programmers to switch to your language, don't make people pay for what they don't want to use.
Support for plugging in a GC would not violate that, but enabling/requiring a GC by default most certainly does.
I wouldn't use go for numerical simulations but it certainly shines for writing network servers.
In the end, when I code in C++, it's because I believe my code will run faster and generally use less resources, and I'm ready to accept the sacrifices it takes (in terms of my own time) to get there. Does it make me someone for whom software is about "doing it in a certain way" ? Probably. If that certain way is "performance" for problems where it matters, I'm even proud of it.
C++ programmers don't come to Go because it turns out Go doesn't shine on problems where C++ was the answer. Simple as that, and there's nothing wrong with that, as long as Go found its niche and solves some problems relevant to him. I'm not sure I see why Rob Pike needs to be so dismissive.
People fucking around with distributed web applications are so immune from the specific cost of adding a line of code because rarely is what they are writing executed repeatedly in a tight loop and thus they lose the ability to quickly measure performance impact
If your code consumes more than 300 cores, you should care about performance. If your code consumes less, you should care about productivity.
Adding cores is easy while adding programmers is hard. Cores scale linearly while programmers don't. So I set the guideline at 1000 cores. Do not make performance-productivity tradeoffs below that.
It certainly can't. And for example you can't do that on an app that runs on a phone, for example.
But, when possible, this is the cheapest way to do it.
Not to mention other cases where it's the "only" way to do it (like, CPU heavy processing, video processing, simulations, etc). A smart developer can help with a %, but with limited returns.
For example, Facebook invested on their PHP compiler since their server usage would only increase, and the resources for that gain (in terms of people) are more or less constant.
There's a lot of B.S. that comes with C++, and there's an entirely different kind of B.S. involved with writing things in Java + Hadoop.
Personally I stay out of the C/C++ ecosystem as much as I can because threads are never really going to work in the GNU world because you can't trust the standard libraries never mind all the other libraries.
The LMAX Disruptor shows that if you write code carefully in Java it can scream. They estimate that they could maybe get 10% better throughput in C++ at great cost, but the average C++ programmer would probably screw up the threading and make something buggy, and a C++ programmer that's 2 SD better than the mean would still struggle with cache line and other detailed CPU issues.
The difference between the LMAX Disruptor and the "genius grade" C++ I've seen is that the code for the Disruptor is simple and beautiful, whereas you might spend a week and a half just figuring out how to build a "genius grade" C++ program, taking half an hour each pop.
Having said that, C++ can be ugly as hell.
Back in the 1990's, when JIT compilation was new, I wrote a very crude implementation of Monte Carlo integration in Java that wasn't quite fast enough to do the parameter scan I wanted. I rewrote the program in C and switched to a more efficient sampling scheme.
When it was all said and done, I was disappointed with the performance delta of the C code. Writing the more complex algorithm in Java would have been a better use of my time.
1) UTF16 strings. Ever notice how sticking to byte[] arrays (which is a pain in the ass) can double performance in java ? C++ supports everything by default. Latin1, UTF-8, UTF-16, UTF-32, ... with sane defaults, and supports the full set of string operations on all of them. I have a program that caches a lot of string data. The java version is complete, but uses >10G of memory, where the C++ version storing the same data uses <3G.
2) Pointers everywhere. Pointers, pointers and yet more pointers, and more than that still. So datastructures in java will never match their equivalent in C++ in lookup speeds. Plus, in C++ you can do intrusive datastructures (not pretty, but works), which really wipe the floor with Java's structures. If you intend to store objects with lots of subobjects, this will bit you. As this wasn't bad enough java objects feel the need to store metadata, whereas C++ objects pretty much are what you declared them to be (the overhead comes from malloc, not from the language), unless you declared virtual member functions, in which case there's one pointer in there. In Java, it may (Sadly) be worth it to not have one object contain another, but rather copy all fields from the contained object into the parent object. You lose the benefits of typing (esp. since using an interface for this will eliminate your gains), but it does accelerate things by keeping both things together in memory.
3) Startup time. It's much improved in java 6, and again in java 7, but it's nowhere near C++ startup time.
4) Getting in and out of java is expensive. (Whereas in C++, jumping from one application into a .dll or a .so is about as expensive as a virtual method call)
5) Bounds checks. On every single non-primitive memory access at least one bounds check is done. This is insane. "int[5] a; a[3] = 2;" is 2 assembly instructions in C++, almost 20 in java. More importantly, it's one memory access in C++, it's 2 in java (and that's ignoring the fact that java writes type information into the object too, if that were counted, it'd be far worse). Java still hasn't picked up on Coq's tricks (you prove, mathematically, what the bounds of a loop variable are, then you try to prove the array is at least that big. If that succeeds -> no bounds checks).
6) Memory usage, in general. I believe this is mostly a consequence of 1) and 2), but in general java apps use a crapload more memory than their C++ equivalents (normal programs, written by normal programmers)
7) You can't do things like "mmap this file and return me an array of ComplicatedObject[]" instances.
But yes, in raw number performance, avoiding all the above problems, java does match C++. There actually are (contrived) cases where java will beat C++. Normal C++ that is. In C++ you can write self-modifying code that can do the same optimizations a JIT can do, and can ignore safety (after proving to yourself what you're doing is actually safe, of course).
Of course java has the big advantage of having fewer surprises. But over time I tend to work on programs making this evolution : python/perl/matlab/mathematica -> java -> C++. Each transition will yield at least a factor 2 difference in performance, often more. Surprisingly the "java" phase tends to be the phase where new features are implemented, cause you can't beat Java's refactoring tools.
Pyton/Mathematica have the advantage that you can express many algorithms as an expression chain, which is really, really fast to change. "Get the results from database query X", get out fields x,y, and z, compare with other array this-and-that, sort the result, and get me the grouped counts of field b, and graph me a histogram of the result -> 1 or 2 lines of (not very readable) code. When designing a new program from scratch, you would...
Second, I've seen companies fall behind the competition because they had a tangled up C++ codebase with 1.5 hour compiles and code nobody really understand.
The trouble I see with Python, Mathematica and such is that people end up with a bunch of twisty little scripts that all look alike, you get no code reuse, nobody can figure out how to use each other's scripts, etc.
I've been working on making my Java frameworks more fluent because I can write maintainable code in Java and skip the 80% of the work to get the last 20% of the way there with scripts..
Some problems can scale out, but only if latency between nodes is low enough and bandwidth is high enough. For example, an MMO server would not function as well if there was a 50 msec ping between nodes. You may or may not have control over that depending on what cloud service you use.
These are real concerns and should not be trivialized as "BS for BS" or "throw more virtualized CPU cores at it". Every problem is different; it should be studied and the best solution for the problem applied.
In that case it is a matter of one kind of BS (wondering why you don't get the same answer with the GPU that you do with the CPU, waiting 1.5 hours for your C++ program to build, etc.) vs another kind of BS (figuring out problems in parallel systems.)
Not all problems scale out like that, but you can pick the problems you work on.
Cores scale linearly, but performance may not scale linearly to cores.
You certainly could pull off this architecture in a setting with a good LAN connection. Though I'm not really arguing that it's necessarily a great way to go.
It is entirely technical. Everyone who tried it shit all over it because it was a terrible experience, entirely due to limitations of internet connectivity (both latency and bandwidth).
The primary reasons these services didn't take off is that many users have shitty connections and almost everyone has a fast enough computer.
That is gibberish. If I work at a company and we have 5 machines with 12 cores apiece already in place that is what I have to make do with. We don't all live in an elastic world.
Further to that the scaling of large single computations across cores is a costly and often pointless exercise.
Some places are so inelastic that developers get hand-me-down laptops from sales people who couldn't sell, or when they buy a new machine from Dell they get one with two cores.
She was stressed because there wasn't any official channel for us to buy office supplies other than the stuff they sent us.
I told her to buy the office supplies and say that she worked another 2 hours; this was breaking the rules but this did not strike me as at all unethical.
Now, not long after the 2008 crunch I was getting pissed about how long builds took on my cheap laptop (on which I was running both the client and server sides of a complex app).
Getting a better machine from management was out of the question, but I liked other aspects of the job, and 2009 wasn't the best time to go job seeking. So I bought myself a top end desktop computer and three inexpensive monitors.
When I left that company they wanted to buy the machine off me so as to keep all the proprietary code and data on it, but as things worked out, the value of my own proprietary code and data on that machine was worth a lot to me so I kept it, and fortunately things never went to court.
This type of decision has risks (for instance, you don't want to be the guy who loses a machine with social security numbers on it and forces his employer to pay for credit monitoring for 70,000 people) but it can be the right thing to do sometimes.
In the long run, I think companies that value human capital appropriately will win.
I mean, if you're just serving some simple webpage, it's easy to just throw servers at it. But if you want to implement say a distributed k-means, the algorithm is different than for the single-threaded case. Not everything is easily scalable...
You need to get out more, you've completely lost perspective.
(Note: I work for Google, but on open-source server software.)
It does not: http://en.wikipedia.org/wiki/Neil_J._Gunther#Universal_Law_o... and http://en.wikipedia.org/wiki/Amdahl%27s_law
Not only it does not but sometimes it doesn't scale at all. Scaling software is a very difficult problem, especially when you have low latency issues.
And what happens when you write desktop software? You ask your customers to open Amazon accounts?
So I set the guideline at 1000 cores. Do not make performance-productivity tradeoffs below that.
In which field do you work?
They hire Amazon before playing my physics game?
Oh, I know, just put the game in the cloud...
Then players will become angry because the game only works when internet works and they cannot play at the underground train while commuting.
Sorry, but sometimes I have impression that web developers forget there is other sort of development that exists.
Computing time is cheap these days, but this kind of math doesn't make any more sense than comparing feet to miles per hour. Programming time saved is a one-time gain, whereas the performance loss in continuous. Let's say you write code for a single core, you spend 10 hours instead of 20 by accepting a 50% slowdown, and manage to compensate by adding an extra core. Depending on how long this code runs, there will be a point at which the ongoing costs of an extra core surpass the one-time saving of 10 hours' programming.
If all you need is a working prototype then sure, performance shortcuts may be worthwhile. (Although you can't calculate trade-offs as suggested). But for long-term production systems they will always start hurting at some point.
That said, what makes sense for Google doesn't necessarily make sense for the rest of us.
In practice, I think a lot of programmers simply don't know how to call C/C++ from python, even though it has become so much easier since ctypes. Thus doing this is derided as a waste of time, dangerous and whatever. You'll soon see that doing this has other advantages (like type safety).
You don't seriously think that do you? People struggle with concurrency and parallelism all the time. Tons of problems we have no way to scale up with more CPU cores, it is an open research problem to try to find ways to do so. Pretending that you can just buy fast is a huge mistake that costs millions of dollars.
There are also some tradeoffs when switching languages. Some people would never make the move from C to C++ citing unnecessary complexity (e.g. Linus Torvald).
This is essentially a question of having the right tool for the job. Switching from C++ to Go is probably a good decision some cases and a bad one in others. But one should not remain so anchored in one language that won't be able to consider some other, probably better, option.
People who 5 years ago were sermonising to me on premature optimisation are now telling me they're rewriting something in a faster language or how many millisecs they've saved using some new profiling snake oil they've just bought.
(whilst my background is in assembler/C, I now prefer to use prematurely optimised Ruby where possible just for the maintainability and the magic)
Knuth's original statement on premature optimization presupposed that the cost of optimizing later isn't really that much higher than optimizing now. I mean, obviously it's going to be somewhat harder - code is harder to read than to write, and fixing a performance failure is going to take longer than getting it right the first time. But still, that's not a humongous cost and there are so very many opportunities for optimization that chasing them without performance data is a waste of time.
But when you have an actual barrier to optimizing? Then you've got a real problem. If you're committed to a technology that has a hard performance ceiling and no easy way to break the slow parts out into another technology? That's a different problem.
It seems evident that Knuth's advice about premature optimization can be indiscriminately applied when you're talking about code for an individual component... but should be considered carefully against the potential costs when thinking about large architecture.
Building software is hard, and it's not at all surprising (or reprehensible) that people will seek out shortcuts to winnow their decision space.
Most people I've known have used it as shorthand for "decisions based on optimization concerns require some justification that the optimization is important to the specific application and warrants the cost that come with it"; it's not an appeal to authority (indeed, the authority behind it is almost never referenced, just the bare quote), and its usually, IME, a defense against a preconceived, ideological decision (it works poorly to justify a preconceived, ideological decision, because it doesn't have carry much weight if the person proposing the optimization has any basis for making the claim that the proposed optimization isn't premature; as it shouldn't.)
* Performance doesn't matter for a large set of systems we write. * Performance is far more a product of the programmer than the language you use (within reason, naturally. Don't do Video decoders in Python :) * Large-scale systems where there is no single tight loop anywhere are way different beasts. Their performance stems largely from fast RTT in the edit-compile-test cycle and programmer productivity. Not from fast native code execution. * To some problems, latency or sustainability matters more than throughput.
Completely agreed and exactly my point. I am not moving to Go because is solving problems that I don't have.
Pike said: "That way of thinking just isn't the way Go operates. Zero cost isn't a goal, at least not zero CPU cost."
So Go's philosophy is to make some compromises for the sake of making programmer's life easier. C++ is the other way around, there is a cost the programmer has to pay in other to have code abstractions without impact the performance.
I don't think anyone "loves" to code in C++, but people tend to like the performance that C++ provides and are eager to pay the cost of programming in a monster language that no simple person fully understand.
The problem is that some of the baggage of the former interferes with the latter. C++ is danged ugly in some places in ways that could be expressed cleanly in higher-level languages.
That's what C++ coders want - C++ with modules and real generics and fast compile-times and ways to cleanly implement and use garbage-collection if you so choose. A language that lets you say incredibly complicated and detailed things, and then lets you abstract them away into a library or a class or some other unit of organization that lets another coder use your stuff without absorbing the complexity.
All these "C++ replacements" assume that the solution is to gut out all the C-like stuff. What they should be looking to do is giving developers clean alternatives to the C-like stuff, including ways for the hardcore developers to provide their own clean alternatives to the C-like stuff. Don't give us garbage collection, give us the tools to write libraries that provide clean garbage collection to a developer.
I got lost with the "Java-like context" thing. If I am not mistaken, by the time that C++ was designed there no language with a GB other than Lisp dialects. Jav a would appear like 12 years after, so I am not sure what you mean with Java-lik e context.
As for the design goals of C++, I think was actually to create a superset of C t hat allow to give abstraction facilities that C doesn't have (starting with OOP but right now way more than that)
Lisp, Smalltalk, Ada, Simula, ML, ...
Simula was the inspiration for C++ by the way.
That's the difference: in C++ you get the abstractions -- just like in Java -- but you don't pay for them.
For the record: I used Java extensively in my previous job. It's a language I love, and I do think there are many areas where its speed is sufficient. But I'm also quite fond of C++, and there is this nice feeling of "woah, it doesn't really get faster than this, and it's still readable and elegant!" :)
That's not enterally true, you do pay for them, not in performance but in productivity. C++ is a complex language and even Alexandrescu touched this subject in Going Native 2013, he said something like "C++ is a language for experts"
Not bashing the language, just stating the sad state of affairs.
I do. :)
It's a trade-off. Assembly is an order of magnitude less productive, and it doesn't offer significant benefits. Outside of your critical path, you might actually hurt your runtime performance unless you really, really know your instruction set. When people say 'C trades speed for ease', they don't mean they want to design an ASIC to make their operation blazing fast. They mean C is at a sweet spot of developer productivity and execution time, for their specific application.
There is a trade-off between developer productivity and runtime performance. The author said that Go is appealing to people coming from a Python or Ruby background, which is a strong indicator that Go has fundamentally gotten the developer productivity side of the equation right.
So we should try and think about how the equation balances here. Is Go an order of magnitude slower than C++? Don't know. I think its not, though. My impression (which might be wrong, so please correct me if necessary) is that Go programs run approximately as fast as C++ programs that are written using C++ automatic memory features like smart pointers. Is Go an order of magnitude faster to develop than C++? Again, I'm not sure, but my perception is that it probably is. Python devs wouldn't be interested in it otherwise.
It does not similarly dominate C++. C/C++ cannot be replaced by something like go for the very simple reason that it wouldn't work. Go itself depends on a C runtime and a C compiler written in C, even ignoring the operating system it has to run on (which also cannot run without a C/C++/assembly core). The same goes for languages like Java, Erlang, Haskell, ... (Java is particularly bad, since it has a huge complicated runtime which is almost completely C++)
After all, who will garbage-collect the garbage collectors ? (this is a simplification, the garbage collector is a major problem, but not the only one. There's dozens)
In average, C++ is three times faster than Go in all the tests. These benchmarks aren't definitive but you can assume that in general the difference in performance is much less than an order of magnitude.
Now, look at the same comparison between Go and Python3: http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?t...
Python3 is in average 20 times slower than Go. And I love Python but Go isn't that much harder to use. It's quite a nice language, actually.
So, the exodus from Python to Go is very understandable, you gain a lot of performance without sacrificing much. And I think there's room for performance improvements in Go, perhaps in a couple of years C++ developers will make the transition. But I think that the real C++ killer is Rust. Time will tell.
If your work consists of writing extremely demanding code WRT performance, then it probably is useful to stop and think for certain projects, or portions of projects, whether it's worth going to assembly.
Similarly, if you find any utility in going lower in the language stack, it might be worth going higher for some projects or portions of projects.
Whether you actually use anything else is up to you, but blind adherence to a specific language is limiting, and may well be detrimental to the work you are trying to accomplish.
(you in this context is general, not applied to the parent specifically)
Even Go uses assembly in places -- for example, bytes.IndexByte.
The point is that C++ still has real performance benefits over Go, and it's not just used out of cussedness or backwards-thinking. (Though Go can be pretty close. I think it's a shame that didn't go w/ a simple-refcounter + weak references approach to GC.)
* I read a lot of compiler-produced assembly -- these days it's often surprisingly clever. I don't think most developers could beat them with hand-coding even if they were willing to spend 10x-100x the time in development and debugging.
* As other people on the thread have mentioned: it's all about the memory. In a world where a cache miss is going to cost ~100 cycles the actual instruction stream isn't even your biggest concern -- programming for performance increasingly means counting cache lines. I can do that just as well with C++ code as I could with assembly, at least as long as the compiler provides things like prefetch primitives, etc.
There are still some super fast-path areas where expert assembly can beat a compiler (crypto algorithms, ...) but it just isn't attractive for most projects no matter how much developer time you're willing to spend.
I've never seen anyone defend the idea that writing something in C++ will necessarily make it high-performance and I would be very, very surprised if that's what the OP meant.
It most certainly is. In fact, it's the answer to the opening question, "Why does Go, a language designed from the ground up for what what C++ is used for, not attract more C++ programmers?" You might not have noticed it because he only refers to the performance issue as a "Zero (CPU) cost" mentality.
> C++ is about having it all there at your fingertips. I found this quote on a C++11 FAQ: > > The range of abstractions that C++ can express elegantly, flexibly, and at zero costs compared to hand-crafted specialized code has greatly increased. > > That way of thinking just isn't the way Go operates. Zero cost isn't a goal, at least not zero CPU cost. Go's claim is that minimizing programmer effort is a more important consideration.
Yes, Go is slower but it's not slower because of fixing those errors, it's slower because it introduces different features suitable for its niche (GC, reflection etc) Rust takes similar approach to avoid C++ design mistakes and doesn't sacrifice performance in doing so.
Those mistakes (mainly the whole "object model" thing) is what he is saying in the article. Pointing out performance of Go isn't really an argument against his point.
"C++ programmers don't come to Go because they have fought hard to gain exquisite control of their programming domain, and don't want to surrender any of it. To them, software isn't just about getting the job done, it's about doing it a certain way."
It's probably very silly but in my mind that puts it next to Java, above C and C++ in the "grand scale of programming languages".
Oh, and also I don't like garbage collection, so there's that. I'm sure some day someone will explain to me what's the point of it because I still don't get it.
There's no way to make that a local decision that I know of.
This means that you can have different tasks that have GC turned on or off at the task level, because a GC'ed object will never "leak" across a process boundary. However, if you decide you want to parse JSON with your fancy new GC-using JSON library, you either need to put that into a separate task, or you need to enable GC in the task that calls into that library.
That means that if you want GC-free code, you're going to have to be very careful about which libraries you can call into directly.
FWIW, Rust's stdlib tries to eliminate the use of GC whereever feasible. Cyclic data structures and persistent data structures are probably the only places where GC will end up being necessary.
Keeping track of resources is a big part of any software development. You have keep track of open files, user sessions, network connections, memory mappings, all kinds of caches, many other things... and allocated memory. And for some reason this last kind of resource we don't want to keep track of "manually", instead we expect the computer to do that work for us. Why should we handle dynamically allocated memory as a special case of resource management?
Don't get me wrong, I love having my computer do my work for me. I expect my compiler to be able to inline my code for me, optimize my arithmetic, unroll my loops and do all kinds of stuff for me. Stuff it's good at, stuff it can do at least as well as I can and probably much better. Memory management is not one of those things IMO.
I feel like memory management is like pointers in C, it's a mythical dragon that scares those who have never used them beforehand. It's really not that hard or that much of an issue in the real world. If you really can't keep track of your memory allocations then the solution is not to add a GC, you have a major architectural problem.
Ohh... huh...
However, when you have fewer components which can't be combined to achieve certain things that you could do earlier, it is hard to see how you can then say "Less is More".
Coming from game development RAII is a blessing. Not having control of memory deallocation is will not sell. This is definitely not a case of "Less is More", it's a case of "Less is Less".
The only real, modern alternative to C++ is Rust, but it's not at 1.0 yet, meanwhile C++ is still getting new features, all the while preserving compatibility.
Plus all these generated systems are standard and thus you can have different languages linking each other.
Sadly, C/C++ take the world.
Not only that, sometimes you don't want a runtime overhead plain and simple. I don't know anyone in high throughput app development who would be happy with go. You want to generate a sequence of instructions which get executed.
Ok, you can use C/C++ freestanding for kernels, but that does not change the fact that C as a language has a specified runtime.
http://en.wikipedia.org/wiki/Rob_Pike
He has given some really great Go talks which are available on youtube, about an hour each:
Origins of Go Concurrency Style - http://www.youtube.com/watch?v=3DtUzH3zoFo
Lexical Scanning in Go - http://www.youtube.com/watch?v=HxaD_trXwRE
Go Concurrency Patterns (One of my favorites) - http://www.youtube.com/watch?v=f6kdp27TYZs
(NIHS was certainly invented at Bell Labs' CSRG, I'm just not sure of the exact timeline.)
The problem with Pike's work, as I see it, is that what it calls 'simple' I see as unnecessary burdens layered on top. A text editor that makes you take your hands off the keyboard? No thanks. I want to edit text, not pictures of text.
Ah, by the way, did anyone mention garbage collection?
You could do that. Or you could go write a new language and further scatter the masses.
For now, if I'm really wanting concurrency, and don't feel like C++ is doing what I need, I'll grab Java/Scala with Akka. They allow me to create a solution tailored to a problem, rather than tailoring a problem to a solution.