Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Why I Don't Want to Learn Go (arantaday.com)
212 points by dwwoelfel on March 19, 2012 | hide | past | favorite | 137 comments


Go is designed for large codebases, which is a problem that the author may not have, and so he may not see the benefits.

One key feature is that the Go compiler itself is the style guide: it automatically reformats your code to remove style guide violations. This makes it easy to work on a codebase the size of Google's because everything looks like it was written by the same person. We try to do the same thing for C++, Java, and Python, but it doesn't work as well because the process is manual.

Similarly, compilation time and runtime for every component, no matter how unimportant, is of utmost importance for Google's codebase. It may not matter how long it takes to run one one-off script, and it may not matter to you how long it takes to compile, but it does matter at Google because we compile every project and run every test after every commit. (OK, builds and tests that are obviously unaffected are skipped. But it's still a lot of code being built and tested.) So your Python project that takes 5 seconds to run tests instead of 1 second ends up wasting decades of CPU time throughout its life time. Same for C++ projects that take many hours to compile. Go tries to be as expressive as Python and run as fast as Java (and compile faster than anything else), and this saves lots of time in aggregate. (Remember, when you break someone's build, the delay between submitting your change and the system knowing about the breakage can result in a lot of hair-pulling for the developers on the project you broke. But if we can know the build is broken before the change is even submitted, then many hours of developer productivity are saved.)

Anyway, don't take this to mean that you're doing software wrong if you don't see the value of Go. Google is a special case and just because we have some problem doesn't mean you should have the same problems. One-man shops should optimize for individual efficiency instead of aggregate efficiency like Google does.


Go is designed for large codebases, which is a problem that the author may not have, and so he may not see the benefits.

Aren't most serious languages designed for large code bases?

(and compile faster than anything else),

So, why not invest in incremental compilation for an existing language? E.g. the ECJ compiler for Java has done wonders in terms of immediate feedback while developing. clang aims to do the same for C code and slowly makes editors and IDEs more effective.

Anyway, don't take this to mean that you're doing software wrong if you don't see the value of Go.

I fully agree with the author, on the one hand Go does not provide the performance of C or C++, on the other hand it nearly no useful new abstractions to manage complexity. Languages such as Haskell, OCaml, F# or even D provide a better type system and have similar or better performance.

Google is a special case

Out of curiosity: how much is Go used in Google? What percentage of new projects use Go compared to e.g. Java or C++?


> Aren't most serious languages designed for large code bases?

Maybe the big companies like Google and Facebook are approaching a new meaning of a “large codebase”. They have a huge number of programmers, the development is much more distributed into different locations and time zones, and the release cycles are much smaller than they used to be with large codebases in the past. There’s for example this very interesting discussion about the way these companies use their versioning systems:

https://news.ycombinator.com/item?id=3548824

Some of the practices (like keeping their whole codebase in one big repository) look quite questionable, if not downright stupid from a smaller viewpoint, but make sense in their case. Go could be a similar thing – most serious languages are designed with good modularization, encapsulation and other features that support large scale code bases as most of us know them, but that does not mean these languages are a great match for software at the Google scale.


> Maybe the big companies like Google and Facebook are approaching a new meaning of a “large codebase”.

If codebase is that large, language alone can't solve all the problems. Be it compiling time, testing time, or whatever problems large codebase may have. I guess that's exactly what Steve Yegge tried to say in his famous Platform Rant blog post.


SQL isn't, and if it's not a serious language, what is? Perl and PHP are what the web app layer was originally built on, and they seem to be designed to maximize developer efficiency for small projects.

Haskell is definitely interesting. If I wanted to build a large system that was super-performant, I'd look at C, Haskell, and Go. I don't know enough to make a great decision, but all three look good.

Go has the advantage of being designed for the kind of thing Google does - massive concurrency. It's also like C, which make it easier to find good programmers who are confortable with it. Actually, you'd be hard pressed to find good programmers who are uncomfortable with a language that's nearly C. I'm not saying Haskell programmers aren't good programmers, but Google probably doesn't have enough of them, and they'd have to port their existing code to a completely different base (bad idea).

The original article complains about Go's GC. For a single process application, this could be murder. I don't think Google uses a single process.


SQL isn't, and if it's not a serious language, what is? Perl and PHP are what the web app layer was originally built on, and they seem to be designed to maximize developer efficiency for small projects.

I intentionally said most, since, obviously there are serious domain-specific languages. But stating that Go is designed for large code bases, creates a false dichotomy.

Go has the advantage of being designed for the kind of thing Google does - massive concurrency.

So, claims the C fan since there's GCD, so claims the Erlang/Scala fan since it has actors, so claims the Haskell fan since it has green threads, STM, and purity.

Also, is Google interested in massive concurrency or parallelism?

It's also like C, which make it easier to find good programmers who are confortable with it. Actually, you'd be hard pressed to find good programmers who are uncomfortable with a language that's nearly C.

That's a good point. But as a result it provides only a marginally better type system, at the cost of performance compared to C. Why not make it a lot better than C, with the same performance?


Calling Perl domain specific? I think those would be considered fighting words in some places. ;)


I love a certain subset of Perl with a passion bordering on mania. While I wouldn't call it domain specific, I do think it's better defined by the domains it's not well suited for. I wouldn't use Perl for GUI programming for example.

It's kind of a domain anti-specific.


> I wouldn't use Perl for GUI programming for example.

I would. I used the gtk-perl bindings for a project and I thought they were very well done. Previously I had only used the C bindings and taking the step to a higher level language (and more importantly, one with closures) was a very nice step. It was a much better experience than doing Cocoa with Objective-C, IMO, but that could have also been related to the specific (smallish) project I was doing.


> That's a good point. But as a result it provides only a marginally better type system, at the cost of performance compared to C. Why not make it a lot better than C, with the same performance?

For many things, GC is a huge productivity boost. I've heard good things about C99, C will probably evolve into a language with a better type system anyway. I don't use C myself, but I don't see why there couldn't be a flag to ensure code only uses a saner subset of the type system.


I also don't plan to learn Go, but if I have to because it becomes the de-facto standard for some important niche, then I will. This depends massively on the quality of their implementation and also on that of their competition.


> Aren't most serious languages designed for large code bases?

Well, C is basically designed for Version 6 Unix, the Programmer's Workbench http://en.wikipedia.org/wiki/PWB/UNIX and troff, not a very large code base by today's standards.


I think clang has a good chance to became as competitive as Go for compilation speed. This way you will have a fast compile/run process and the power of C or C++.


I could believe it for C (tcc is an existence proof for very fast C compilers), but building a C++ compiler of that speed is a pretty difficult task. Separate compilation for templated code is also really hard to get right, since the standard isn't really designed for it and gives few guarantees; if a templated class is changed, determining when you can safely avoid recompiling classes that use it is tough.


Definitely. I am anxious to see how much C++11's extern template will improve compilation time, when it will be used by large libraries.

Of course it's still a horrible kludge. But the reality is that C++ exists and is widely used ;).


>Go tries to be as expressive as Python and run as fast as Java

Why the seemingly almost complete lack of love for Pypy from Google then? It's not like you can stop using Python anytime soon even if you keep extending Go. I believe Google's made one tiny donation to Pypy. Given their benchmarks (http://speed.pypy.org/) and given Google has literally tens of billions in hard cash lying around I can't see how you can't get them some money. A few hundred thousand to Pypy would be justifiable on the performance improvement YouTube would experience alone. Sure the motto is "don't be evil" rather than "do good" but this seems like a no-brainer. Can you give reasons why it's not happening?


(1) Google spent lots of developer resources on Unladen Swallow, which ended up not giving the speed increases they expected, but that's another story.

(2) Last thing I heard, Google's trying to minimize their Python usage in favor of Java.


Re #2, I heard ~November that Python was deprecated in production at Google. No idea what the details/caveats on that are (I presume it applies mainly to new code?).


Thanks for mentioning that--I'd never heard of that before. (Although it's not like I'm in danger of getting a job there. :)


This is something that I see at many places these days. Scripting has become synonymous with Perl. And for anything else People are really going in for Java.

But Django and Rails seem to be the major reasons why people continue to use Python.

Having said that no company that is making billions in profits is going to bet their very survival on a framework written and maintained by volunteers. Frameworks come and go, Every 5 years there is something new.


"Scripting has become synonymous with Perl."

This is a remarkable claim. Well beyond what the most dedicated perl enthusiast could make with a straight face.

Do you have any supporting data or evidence to back it up?


I have hardly seen any shop so far, at least in the most big/medium corporates who use Python or Ruby heavily in scripting. Its either bash or Perl. The problem is as I said, Neither Ruby or Python were every marketed, designed or even took off as a Scripting languages. Most start ups pick up Python/Ruby basically because they don't need a new language with their existing Django/Rails code base.

Even in such cases one you infrastructure begins to expand, one you are a reasonably sized team. Perl usage becomes inevitable.

Even among the heavy Python using companies like Google, its becoming clear why anybody would not use Python or even deprecate it in production. Because it doesn't quite really have a strong dedicated niche. Php has the web, Perl has the scripting/glue part on the Unix environment. Java has the static large app part.

Python/Ruby have great web development frameworks.But when it comes to scripting, there are no real alternatives to Perl. And besides if you wish to develop large applications, Static languages serve well. There is no point in using Python when you don't want to cook things quickly.

You will be shocked how many places apart from web communities and forums like these people haven't even heard of Ruby and Python. Most of my friends in big companies some of who also lead big teams over the years 'have just had a look at Python'.

I realize that I have posted this in a community that likes Python a lot and I'm likely to be downvoted. But I'm writing just what I've seen over time.


I never trust anyone who uses the designation "scripting language" let alone those who use it with a capital 'S '. There is absolutely no formal definition of this and it's been repeatedly picked apart such that I don't even have to do it here.

Regarding your other comments they seem to be way off base and just using your personal bubble/ "what I've seen over time". Ruby and Python have crushed Perl in modern web development (Twitter and Reddit come to mind among many others). Python has vast user communities in research and science (including computer science teaching now, MIT, Stanford). Perl might be before Ruby in the pack behind R/Matlab/Mathmatica/Python in some research settings, but that's not saying much. Python additionally is the chosen admin utility language of Red Hat and Ubuntu for their Linux distributions, so it seems there are real alternatives to Perl.

I'm not saying Perl is bad, I am just saying objectively it's been in decline since the 1990s against its rising competitors in all areas: universities, other research, Linux systems administration, application development and web development.


AFAIK, Unladen was a 20% project for a couple (less than 5) Googlers, running without any corporate support beyond the 20% system.


I'd guess that C++, Java and NIH are all powerful forces at Google.


Given that Google hired Guido Van Rossum and that python is one of the three (and up until very recently two) supported languages for GAE, I think we can safely assume the Google isn't entirely anti python.


> I think we can safely assume the Google isn't entirely anti python.

I don't suggest otherwise. It's known that Python is one of Google's three languages approved for internal use (or apparently four now that JS has got a foothold). But I'm sure I've seen reports that people are nonetheless being pushed towards Google's other two officially blessed languages, at least on production code - and in fairness, Google is a place where developer time is often cheaper than the machine time you have to spend to save developer time. But moveover it seems that, even when people in Google do want to fix their Python performance issues by making Python perform better rather than by reducing its use, they tend to want to do it in-house rather than by adopting or supporting other people's work: look at Unladen Swallow. That would be in line with the rather hubristic, command-economy approach - "let's hire all the world's smartest people, then order them to build the future" - that seems to determine Google's actions in general. Hiring GvR fits that pattern too (as well as making plenty of sense).

But I'm sure other people here are much better informed about this than I am.


The problem is python never took off as a scripting language. In spirit it was a great language to develop applications in.

This creates a dilemma for a lot of people while choosing a technology. If you have to choose a language where you don't want to develop stuff quickly. Then you now have sufficient time to choose a static language and then develop stuff at the speed desired.

For other quick stuff there is Perl anyway.And it doesn't make sense to use Python, which is slow(compared to java), which doesn't give quick development cycle(compared to perl).

If you wish to relevant for a long time, then you have to do at least one thing properly.


Historically, Sun hired John Ousterhout and that didn't turn out terribly well for TCL backing by Sun.


Fair point. Or for a more recent example, Microsoft hiring Simon Peyton-Jones and yet showing no interest in actually using Haskell for anything.


Well IIRC, he's employed by Microsoft Research, which is not really the same as Microsoft proper. And they have used some concepts that are core to Haskell, such as LINQ being a monad, and F# is definitely related (though I don't know if that's an official Microsoft language).


* (though I don't know if that's an official Microsoft language)*

It is. When you launch Visual Studio >= 2010 it's there alongside C# in the Project Creation wizard.


I think F# is largely based on OCaml. I'm not sure what'd make a language official; MS does the development work on it, so I guess that'd be a yes on officialdom?


To be more precise, F# is based on the non-OO parts of Caml, with a completely different object system so it would be be compatible with .Net objects from other languages such as C#.

IIRC, the original research was going to be into making Haskell for .Net, but there were enough issues (in particular, being purely functional makes interop with C# and the existing .Net libraries radically more difficult) that ML seemed like a better fit.


Ah, thanks. I was going on a vague memory of something read a while back. I wasn't entirely wrong - 40% maybe - so that's nice.


Sure it is, it is even listed on the official Visual Studio page:

http://msdn.microsoft.com/en-us/vstudio/hh388569

Microsoft also sponsors Haskell and OCaml research via Microsoft Research centers.


Companies spend money on things that bring them profits or enable making profits.

Java and C# helped their companies do that.

But with Python,Tcl and Haskell its a little different. Its good for the companies if they off, but if they don't they don't loose anything.


PyPy's memory usage up until now has been quite a bit higher, which makes it unsuitable for some server workloads.

Still, I assume this is fixable, and it's getting more and more competitive in terms of the megabyte-second cost of computation (i.e. if you use twice as much memory but run four times as fast, that can be OK depending on the circumstances).


That's fair - the largest code bases I've ever worked on are all less than ~200K LOC.

They've enforced style by mandating committers hook a linter into a git pre-commit hook, and compilation time hasn't been a huge problem since the languages always support incremental/partial compilation (Java/Lisp for the most part).

I can imagine that not working at Google-scale.


> They've enforced style by mandating committers hook a linter into a git pre-commit hook

Style-related presubmit hooks are a part of every project at Google. Plus readability requirements, etc - style is kept pretty damn consistent.

> compilation time hasn't been a huge problem since the languages always support incremental/partial compilation (Java/Lisp for the most part).

This is the far more interesting problem to solve at scale with a single centralized repository.


We try to do the same thing for C++, Java, and Python, but it doesn't work as well because the process is manual.

Use http://astyle.sourceforge.net and add it to your build process and/or commit or push/pull hooks of your source control.

(I am surprised I have to give this tip to anyone on HN!)


> We try [to make all code look like it was written by the same person] for C++, Java, and Python, but it doesn't work as well because the process is manual.

However, Python, because space is significant, tends to look fairly similar "in the wild". Add minimum adherence to a style guide and you're pretty close to that goal.


> One key feature is that the Go compiler itself is the style guide

Unless something changed in the last six months that's not the case, there is a tool called gofmt that will do the reformatting if you call it.

I'm not really sure I see publishing a style guideline in the form of code rather than english text makes any difference, at least it didn't make it for my go code.

I suspect it has more to do with the fact that some of the developers behind go use acme than anything else.


> Go is designed for large codebases, which is a problem that the author may not have, and so he may not see the benefits.

If Go is really designed for large code bases, then IDE support for go with code browsing, refactoring, debugging and profiling would be developed in parallel with the Go language itself.

Since Go IDE support go only as far as petty Vim and even pettier Emacs modes, I couldn't call go "made for large codebases".



This is addressed on the Go FAQ: http://tip.golang.org/doc/go_faq.html#garbage_collection

The authors believe that they can make GC a low overhead operation in Go and they believe that it's essential to take memory management out of the hands of the programmer to save programmer effort. Lastly, they say that should you need to you can always work around the GC by doing your own memory management (linked example).

It feels like they are trying to honor Hoare's "premature optimization is the root of all evil" by considering non-GC languages to have optimized the wrong thing.


Nobody believes GC is a bad idea, it's a canard to suggest otherwise.

It's that it's a contradiction of terms to say that you are offering a "systems" language but the language in question has non-optional GC.

Go isn't competing with C and C++, it's competing with Java and C#.


Go isn't competing with C and C++, it's competing with Java and C#.

This is exactly why I'm taking a wait & see approach. If it gains enough momentum to develop the kind of tool & library ecosystem Java & C# enjoy I'll learn it but I've wasted enough time chasing dark horse language contenders already.


The "tool & library ecosystem" in Java is one of its main reasons why many people avoids it like the plague.

And that using Java is almost impossible without such tools and 'frameworks' doesn't tell you much good about the language itself.

With Go there is little need for such extra stuff, and the tools that exist are very simple and very useful (eg., gofmt, gofix) without being required to make up for deficiencies in the language.


>This is exactly why I'm taking a wait & see approach. If it gains enough momentum to develop the kind of tool & library ecosystem Java & C# enjoy I'll learn it but I've wasted enough time chasing dark horse language contenders already.

I don't even have to do that. In my world, I'm free to oscillate between C and Python, depending on the problem being solved. Bonus: One can call the other.

I have no need for mid-tier corporate languages like Java and C# anymore. Go can be a "better" mid-tier language all it wants, I still won't learn it because it doesn't do anything better than Python or C currently do.

I actively avoid using or creating codebases so grossly-huge that you need the "bug-avoidance" and performance of something like Java and C# to the point where Python is no longer practicable.

When you need more "performance" because your codebase is too fat, you've got a bigger problem that can't be solved with a faster runtime.

But what do I know? I'm just a startup kid who ran screaming from the .NET ecosystem.


It's hard to love Java as a language but I'll still sometimes reach for it over Ruby or Python or C because it's not that much more verbose and it can get within 4x or so of C++ code without even trying.

And often the large codebase finds you, no matter how hard you try to avoid it, and there you start to appreciate some of the design decisions of Java.


I don't deny it has its place for some people, but it's definitely not my experience that

>Ruby or Python or C because it's not that much more verbose

I've seen some shocking differences in LOC and comprehensibility between Ruby/Python vs. Java code, even when a concerted effort has been made to avoid the typical sins of Java codebases.

You might just be more patient than I am, or a better Java programmer. I don't know. All I know is that I end up experiencing kidney failure every time I have to interact with Java code.


> You might just be more patient than I am, or a better Java programmer. I don't know. All I know is that I end up experiencing kidney failure every time I have to interact with Java code.

I don't experience kidney failure, just a sudden urge to scrape my skull against a rough, brick wall. Life is too short for me to spend it dealing with that crap and the community that insists that "Java's not slow", even though it needs gigs and gigs of memory to run (which takes forever to populate and blows your cache), has no shared libraries, no copy-on-write, no memory protection, and no dozens of other things that Unix has had for decades for a reason.


I believe GC is a bad idea. Programmers should know what their objects are doing.


You are severely mistaken about GC then. GC means to a large extent that programmers should know what their objects are doing. Perhaps even more so than in a non-GC'ed language.

The inherent problem with GC is when you put it into hands of people without that knowledge. Then the GC will save them and reclaim their data, whereas it would otherwise be a space leak and dead program. This means that you will have programs that work, but they will run slowly. GC-fanatics like me say that the program has bad productivity since it spends all its time in the garbage collector.

The advantage of GC though is this: If you know what you are doing, you don't need to manage memory in about 90% of your program. It is often either good enough or way faster than doing it yourself. Both in raw performance and in programmer time. A hint is that most modern parallelizing malloc routines use garbage collection internally to make them run more concurrently and faster :)

For the last 10%, the solution is the same as in any other language. You allocate large chunks of memory and then you handle that memory yourself. The advantage is that you only have to do this for a small part of your program and that means you can build software much faster.

The only place where GC is provably a bad idea is in hard real time systems.


> Programmers should know what their objects are doing.

Programmers "should" do lots of things, but designing as if they actually do is usually a mistake. (If vehicle passengers behaved appropriately, air bags wouldn't be a good idea.)

It's better to design wrt what programmers actually do or get new programmers.


I believe that Rob Pike has made the point that garbage collection is required to make the concurrency model practicable. Being Go's foremost raison d'être, its use of CSP should not be ignored or abused, or you won't be getting much out of Go. That's not to say that low-latency garbage collection isn't interesting, or that Go's authors haven't been around this block. (You might be interested to read http://doc.cat-v.org/inferno/concurrent_gc/concurrent_gc.pdf )


Agreed. But sometimes you can know what your object are doing but not want to manage them.

It's tangential, but in my experience coding in Java or any other GC enabled language doesn't mean you can completely ignore the memory management. You still have to watch for leaks, unefficiencies or anything you would have cared for if you managed memory yourself.


It doesn't always matter in all use-cases, I'm afraid.


Unfortunately, as much as I want to agree with it, the article seriously lacks any credibility. Go claims to present high-level features (namely GC) for low-level system programming. Obviously, this sounds new and ground-breaking. Simply dismissing it on account that "GC is unacceptable [for low level problems]" is nothing short of stating a disbelief: it doesn't prove anything.

If anyone wants to prove any shortcoming, than maybe they should come up with a more technical analysis, or at least some sort of benchmarking.


Do you seriously doubt that the Go GC is significantly worse than the Oracle JVM GC (by the metrics of pause times and throughput)? I don't think I've ever heard anyone suggest that it isn't.

My point with this article is simply that, even if Go's GC catches up to the JVMs (which would be an amazing accomplishment in itself), it would still be too inefficient for serious systems work. I provided several real-world examples to that effect.

If you want benchmarks, check out the numbers from moving some of the critical allocations off heap (and out of the GCs reign) in the Java HBase project: http://www.slideshare.net/cloudera/hbase-hug-presentation


In C, don't people just allocate a slab of memory for critical paths too?


Sometimes, perhaps, but simple malloc/free are much faster and more predictable than what you see in GC'd languages, often mitigating the problem. On top of that, many critical paths can avoid even those by confining their memory allocation to the stack, something that effectively ceases to exist in GC'd languages.


> but simple malloc/free are much faster and more predictable than what you see in GC'd languages

More predictable, very likely. Much faster, this is simply not true. E.g., quotes from an article by Brian Goetz[1]:

  The common code path for new Object() in HotSpot 1.4.2 and later is
  approximately 10 machine instructions, whereas the best performing
  malloc implementations in C require on average between 60 and 100
  instructions per call. ... "Garbage collection will never be as efficient
  as direct memory management." And, in a way, those statements are right
  -- dynamic memory management is not as fast -- it's often considerably faster.
> allocation to the stack, something that effectively ceases to exist in GC'd languages.*

Not true, either. With escape analysis, Hotspot JVM can do stack allocation. The flag of doing escape analysis is actually turned on by default now.

[1] http://www.ibm.com/developerworks/java/library/j-jtp09275/in...


That writeup is certainly interesting, mostly with regard to escape analysis, but it's entirely untrustworthy with regard to the comparison to malloc. First, it appears to base its assumptions about malloc implementations on a paper dating to 1993 (WTF?!), second is that it thinks "instructions" is a meaningful metric for judging performance.


malloc is not "much faster" than GC; it's often a performance bottleneck. That's why any C/C++ project worried about performance writes custom slab allocators, which a GC doesn't prevent you from doing. In fact, the GC frees you from thinking about memory management in most cases so you can focus your effort on optimizing the pieces that count. GC doesn't prevent stack allocation either; C# has explicit stack allocation and Java does it implicitly with escape analysis. The only advantage of malloc is its predictability. Hopefully Go will eventually get a pauseless collector to mitigate that concern too.


My understanding is that go still provides a lot of tools to indicate when you want memory allocated and where the memory will go (which can optionally be left out). If these were used, wouldn't that make it easier for the go gc to perform better?


It doesn't. Go provides stack allocation and heap allocation. Stack allocation is the default (except for some always-on-heap things), and stack allocation is silently converted to heap allocation when you take the address of an object.

Go's memory management story is basically the same as Java's with the "use escape analysis to place objects on the stack" flag enabled. (To be fair, there is one extra thing that Go provides: the ability to allocate objects inside other objects.)


IIRC the Go authors have explicitly said that there's probably a lot of low-hanging fruit for improving their GC implementation -- they were focused on getting something working and out the door.


Where Go fits in seems very clear to me. It is a less memory hungry and less verbose replacement for Java, fit for the age of fine grained parallelism.

Go will never replace C/C++ for embedded systems and operating systems. Go will never replace JavaScript in the browser. And Go will never replace Haskell, Lisp, ML, Scheme, etc, for those who have a very deep interest in programming languages themselves.


As for the GC speed, how do GC and manual memory management compare to the Automatic Reference Counting system that was introduced recently into Objective-C? It looks to me as ARC has the advantages of both worlds: it relieves the programmer from managing memory by hand and has no overhead, as the decisions are made during compilation. I'm a bit frustrated each time people talk about GC and manual memory management and act like they were the only options available.


Check out iGC. The claim is, by tailoring GC to the ObjC runtime in iOS, you can beat ARC's performance with GC. (Look at how ObjC allocates heap and use read/write barriers to reduce the number of roots that have to be traced.)


Thanks for the link! The author expresses exactly my thoughts.

In essence: Go is not a system-level language (GC) and for problems where performance does not hurt so much there are other alternatives.

To add my personal opinion: I would not consider Go for another reason - I will not invest in a language that is backed by one company. I did this once with Java and I will not hurt myself again. Java's start was fantastic but then came all the business crap like EJBs and tons of frameworks.


And before you tell me that the GC isn't that big a deal: it is. Literally every big project I've worked on in a garbage collected language reserves a bunch of memory off-heap at startup and uses that for allocations on the critical path because the GC kills performance.

You could replace occurrences of GC with malloc, switch the language to C, and it would be just as factual. Basically, what the author is saying is equivalent to, "Real projects have to optimize." Well, yes. This isn't deep. It certainly isn't surprising, and it doesn't strike me as a good reason for not learning a language.


It's different, because I'm saying that much system level work has to optimize by not using a garbage collector. I've literally implemented off-heap malloc()/free() in Java because GC is so untenable.

I argue that makes a language with has a GC that you can't avoid (as far as I know, it's impossible to allocate an 'object' off-heap in Go) a fairly poor choice for much system level work.

Which means, if Go is to find a niche, it's got to be at a 'higher-level.' And that requires competing more directly against Java or Python - a much higher bar than trying to be better than C.


I don't think you're getting his point. I can still replace GC with malloc() and we end up with the same criticisms of C that you have of Go and Java.

> I'm saying that much system level work has to optimize by not using malloc(). I've literally implemented off-heap malloc()/free() in C because malloc() is so untenable.

Anyone who has had to write fast C programs that make a lot of small objects eventually ends up here. You end up incorporating some sort of pool based allocator, which I'm sure you can come up with in Go just as you can in C (or Java, or whatever).


You could make the same kind of criticisms, but not with the same strength. there are real quantitative differences between the speed of explicit malloc/free and even a really nice garbage collector. (Unless you have a very special allocation pattern, like a whole lot of short-lived allocations and a generational garbage collector that uses stop-and-copy for the nursery generation. That's like the best possible case for GC.)


1 - a whole lot of OO and functional Lisp programs use your "very special" pattern of short lived allocations.

2 - You can rig the game so generational GC beats malloc/free.

3 - It's not a criticism, it's a general principle. One always pays for performance. If your performance requirements are low enough, you can even take out a loan on them, so to speak, by using a more expressive language.


Outside of professionals and core contributors who write performance critical C, most folks haven't done a whole lot of work with a profiler with C programs. One doesn't get performance for free. It's paid for in some way, shape or form. The only thing that's up for grabs is how and when you pay for it. The costliest form of payment is developer hours, which you try not to pay if you can avoid it, though you sometimes can't avoid it.


Why I have learned go:

The overlap between problems that I'd like to solve with node.js and go is pretty large and I prefer being able to use a statically typed language with coroutines and multicore support built in.

The libraries are great for server side programming.

Go optimises for both speed and memory usage. Folk who run benchmarks often seem to ignore the latter but given how the cloud is priced, optimising for memory usage can be a big win.

Go's GC is suboptimal at the moment. That said, I suspect that it'll improve pretty quickly. Go benefits from all those lessons learned during the man centuries spent building the Java GC.


I understand and recognize as valid all of the author's concerns. I am personally using Go for things that I used to do in Java. I recognize that this may not be realistic for people heavily invested in the JVM, but I'm finding development with Go to be much more enjoyable than Java.


I agree with the GC point. If I'm using a low-level language, my litmus test is "could I write an OS Kernel in it".

I have a naive question: could GC in Go be replaced with something like Apple's Automatic Reference Counting (ARC)? It could be an optional feature backed by inserting real alloc(), retain(), release(), and destroy() calls, so you'd still have full control if you wanted to turn it off.


The thing with Go is, it's really easy to write your critical path in C and then write the other 95% of the code in Go and not have to deal with crap like null-terminated strings and a lack of built-in data structures.

Go has better integration with C than any other language I've seen.


Better than C++ and D? You must be joking.


Ok, not better than C++ and I haven't used D. I should've said "other mid-to-high-level langauge". But using C++ doesn't solve my complaints about the clunkiness of the non-critical path stuff. Still have wacky string handling and I'd rather write my own bintree or hashmap than have to use STL.


And throw away years of experience in optimization from the compiler developers?

You surely have lots of free time available.


In fact I don't, which was why I said "critical path in C, rest in Go". Usually I do Java but if I need to use C, I'd like to just write the part that needs to be fast, then drive it using something else. Python is also acceptable when it comes to parsing command line options and the like, and it's as slow as dogshit.

"Lots of free time" would be dicking around with cryptic STL error messages.


Why can't someone make a language where you can optionally use GC on one chunk of memory and use automated reference counting on another chunk? Tell the compiler which variables should be in which category, and then most of the quick programming is done in GC while all the stuff that needs to be performant will be in reference counting but automatically managed so you shouldn't have to know outside of the one keyword to flag the variable and occasionally breaking a cycle when you want to free a structure (or using weak references like Obj-C allows).


I'm not very familiar with it, but doesn't C# or the CLR let you do something like this with managed and unmanaged code?


Modula-3, Ada, Oberon are just a few of such languages.


I wonder why aren't they using something like ARC in ObjC instead of GC ?


I think a large portion of online life is already ruled by Google. I will never use Go only because it comes from Google. A mobile with Google's OS, a Google browser and Google for email and now we will also code in a language controlled by Google?

I have nothing against Google, but as a community of web developers our interest lies in diversifying and ensuring that no one gets more powerful than us.

Also looking at the features of Go itself, it seems to me that the languages caters to many needs of Google and not many of us may have those needs.


I don't like giving over my life to Google either, but there's a big difference between using Gmail for everything and writing programs in Go. Go is an open source project. You can fork it right now if you want, call it Not-Evil-Go or whatever, and BAM it's no longer controlled by Google. They can never make it just up and disappear, the worst they could manage is to do like Oracle did with OpenSolaris and force the community to fork it.


In light of C++11, I see Go as something rather obsolete. I see absolutely no reason why I should spend my time on a language that's different just for the sake of it, instead of studying new features of C++.


Article summary: Go is a "better" Java. Why would it claim to be a systems programming language?

It is a fair point. If anything it illustrates that Google have mis-marketed the product rather than anything else.


I concur with the concurrer and the author with my own more 'positive' addendum:

I just want a cleaned/tarted up C. Something that doesn't make the critical mistakes of Go and Obj-C (adding runtime overhead), but adds optional compile and runtime semantics that can be very helpful and powerful.

Some ideas:

No GC. This is NOT negotiable. I'm tired of belabouring that point.

Give me something nicer than the current C bitfield syntax.

Bounds-checked arrays...optionally. Make the distinction very obvious in the code/type-signature.

Higher-order functions, optionally. I don't really want an object system, just the ability to utilize callbacks in perhaps a nicer way than how function pointers currently function. I'd actually be happy with a standardized syntax sugar for function pointers.

Compile-time (only!) duck-typing and polymorphism. This part I think Go got right, but its sins were too great and the problem it was solving too poorly defined to make up for this.

Unicode-native from the ground up.

Clean up the string/array/pointer conflation, adopt the semantics of the bstring library as the default string type for the language, but leave open the door for 'raw-er' string implementations.

Don't reify language types without enabling people to implement their own data structures at the nitty-gritty level.

Cross-OS green-threads might be nice. Let people define their own concurrency models and semantics on top of what the language provides by default though. Same problem as the language type reification, don't delude yourself into thinking you've solved the world's problems with your subset of solutions. Let people use things like ptrheads without punishing them for doing so.

But most profoundly of all:

Make a language that would make writing a library like libev or libevent less bug-ridden and a lot more fun.

P.S. I sincerely hope someone writes a "pragmatist's" systems language like this.


Wasn't bitc trying to do some of that stuff?

An other option you might want to look into is Rust[0], especially since the language is still in its early days (0.1) and the developers are more than willing to fix things which don't work.

* It does not have bit fields or bounds-checked arrays (which it calls vectors) at this point I think

* A bit of GC: it has a reference-counted pointer type, which is task-local, which might be possible not to use at all (not sure) if you don't want it. It also has unique pointers (reclaimed when they vanish out of use) and stack allocation.

* HoF, unicode-native strings (although they're char vectors so maybe not ideal), pointers cleanups (and more than one pointer type which you may or may not agree with), "tasks" ("green processes"), absolutely trivial C interop (so you should be able to easily use pthreads I think), structurally typed records, tuple types, lots of pattern-matching love (for dispatching and unpacking), explicit mutability marker

[0] http://www.rust-lang.org/


We're working on improvements to the language (namely, regions and dynamic arenas) to make it possible to not use the reference-counted pointer type at all if you don't want it, while retaining the type safety. Regions have their own set of costs, as we're finding out (mostly due to the annotation burden if you start doing complicated stuff), but I think we'll be in a nice sweet spot. Rust gives you three basic options:

(1) Regions, when you want safe, low-overhead allocation. The downside is a more complex type system. (Usually you don't see the complexity unless you're returning pointers that contain references to the stack, at which point you have to convince the typechecker that you aren't creating dangling pointers by doing so.)

(2) Safe, garbage collected heap allocation. This gives you maximum flexibility at the cost of runtime overhead.

(3) Unsafe pointers. This lets you manage your memory manually, like C++. Of course, this is unsafe.

Also, I suspect we're going to add fixed-length vectors; we've been discussing this quite a bit lately and I think there's general consensus that they should be present in the language in some form.


Been following Rust and bitc. I'll leave bitc alone and instead comment on Rust:

Rust gets a lot closer than Go, but is still straddling this awkward territory between C and Java.

I would imagine that Rust would be fantastic for implementing a database or a web browser or anything else equally complexity-management and performance driven. The concurrency and safety semantics seem to make that case even stronger for making it an excellent language for a database.

The non-optional runtime overhead that I have to imagine is endemic to the purported feature-set would seem to be a non-starter for systems (kernel, driver, embedded) programming.

Safety is one thing, mandatory safety means a mandatory runtime overhead with a mandatory reduction in control and power over the code which is unacceptable.


So we basically use the runtime for three things: (a) the task system, which features lightweight threads like Go or Erlang; (b) stack checks and growth; (c) garbage collection. We used to use it for more, but lately more and more stuff has been moved out of the runtime to be written in Rust itself.

I'd like to see a "runtime-less Rust" myself, because it'd be great if we could implement the Rust runtime in Rust. This might be useful for other things too, such as drivers or libraries to be embedded into other software. (The latter is obviously of interest to us at Mozilla.) Rust programs compiled in this mode would disable the task system, would be vulnerable to stack overflow (although we might be able to mitigate that with guard pages), and would require extra work to avoid leaks, but would be able to run without a runtime.

If anyone is interested in this project, I'd be happy to talk more about it -- we have a ton of stuff on our plate at the moment, so we aren't working on it right now, but I'd be thrilled if anyone was interested and could help.


> I would imagine that Rust would be fantastic for implementing a database or a web browser or anything else equally complexity-management and performance driven.

Yeah that's about what I'd expect considering the language's goals.

> Safety is one thing, mandatory safety means a mandatory runtime overhead with a mandatory reduction in control and power over the code which is unacceptable.

Rust has the `unsafe` escape hatch for this, unsafe blocks can do whatever the hell they want and are "unsafe function" and "unsafe pointer" types which are known to bypass Rust's safety mechanism and can only be used in unsafe blocks.


Then it might work out fine, I don't know.

In general I have to work off of their purported goals and priorities to get a feel for where the final destination of the language will be when it's more complete.

If they say they aren't going to prioritize machine semantics, C-level runtime performance, or systems-grade control over code generation then I have assume those priorities will fall wayside to the established priorities of safety and concurrency.

I'm not saying Rust will "fail" like Go seems to be doing so far, I'm just saying I don't think they're going to prioritize making Rust useful for driver development[1].

[1] Which I think is brilliant anyway. It's solving a very hard problem that needs solved.


Your hunch is correct, Rust's developers have stated that Rust isn't aiming to be a language with which to implement kernels or device drivers.[1]

It's interesting to see that the domain of "systems" programming languages appears to be splitting into "kernel-level" domains and "perfomance-critical application-level" domains. In this light, it seems more like C++ is the one caught straddling the gap. Should be interesting to watch this space for the next decade or so.

[1] https://github.com/mozilla/rust/wiki/Doc-project-FAQ


I'm not saying Rust will "fail" like Go seems to be doing so far

I think it's way too early to tell if Go is failing or not; it was announced less than three years ago. How successful was, e.g. , Ruby in '98?


Go isn't failing. It's actually doing quite well. I disagree with the design and implementation of almost every part of the language, but credit where credit is due: Google has created a language that a lot of people like.


Have you had a look at Clay? http://claylabs.com/clay/


It's the most promising out of the current cohort that includes Rust, I'll say that much.

Clay seems to understand that you cannot compromise.


"Clay seems to understand that you cannot compromise."

Perhaps I'm cynical, but having had no experience with Clay this statement fills me with dread. Care to elaborate?

Edit: ah, I see elsewhere you've defined what you mean by "no compromises." Still, I'd be interested in hearing what makes Clay the front-runner in this field if you care to tell. :)


From a language level, Clay offers a lot of features over plain old C: strong typing, type parameters, polymorphism, etc. All of the additional features map onto the machine in a very specific way, giving you the same kind of control that structs, arrays, etc. do in C. It doesn't force garbage collection on you. You can even call external C functions by simply declaring them, similar to how you would do it in C itself.

Clay seems to have a lot of potential in the systems programming space. The language is still in a bit of flux, but it's the first C alternative that still has me excited after using it (which can't be said for C++, D, Go, or Rust).

The folks in #clay on freenode are very friendly and helpful. You can tell that they've been keeping up with advances in PLT but that they also understand the kinds of low-level things systems programmers need to do.


The funniest and most succinct reply I can muster for you is that Clay is the programming language least designed for quiche-eaters.

I leave it to your Google skills to get the cultural context for that. :)


I'm curious if anybody has written something equivalent to CoffeeScript for C...


Something that provides syntactic sugar that compiles down to C? You'd be looking for Vala[1]. I haven't used it so I can't vouch for it in practice, but I know it compiles to C and uses the GObject system for object-oriented programming. It's not as much of a syntax change for C, but it apparently adds quite a bit semantically. There's also a Scheme implementation called Chicken[2] that compiles to C source, and I know there are others that I'm not recalling off the top of my head.

[1]: https://en.wikipedia.org/wiki/Vala_%28programming_language%2... [2]: https://en.wikipedia.org/wiki/Chicken_%28Scheme_implementati...


As I understand it, this fellow named Bjarne Stroustrup did once. Of course, the project eventually grew beyond its humble beginnings...


>>No GC.

Interesting that you disqualify Objective C? It use reference counting which should have a more predictable memory handling behaviour.

Or is the dynamic stuff too much overhead for you? To me, it looks cheap (but I'm a scripter since quite a few years).

(Not knowledgeable on this; I'm asking, not making an argument.)


Objective C message passing is much, much faster than function dispatch in a typical scripting language but still too slow for inner loops. C++ virtual functions and, of course, inlined C/C++ functions are much faster.


Obligatory link benchmarking various Objective-C operations:

http://www.mikeash.com/pyblog/performance-comparisons-of-com...


I'm a bit concerned about at least one measurement:

Read 16-byte file 100000 iterations 2.1s for 100k reads 21219.3ns per read

This appears to be testing... the filesystem cache? It's certainly not seeking on a rotational disk, "SSD" isn't on the page, so... not sure where he's getting 21 microsecond reads from.


It's measuring the overhead of a set of open()/read()/close() syscalls - exactly the situation where you would want to use the cache to avoid physical disk latencies swamping the language variation.


Then it should say so, not suggest any rereading is being done and that it's just kernel plus memcpy.


> It use reference counting which should have a more predictable memory handling behaviour.

Correct reference counting in multi-threaded code running on a multi-core machine adds significant cost to a simple pointer copy (aka "add reference").


It seems most people don't really understand the core of systems programming.

Let me try to summarize:

There can be no limitations of any kind in terms of expressing to the machine, precisely how the machine should behave.

Period. No ifs-ands-or-buts about it.

This means you must be able to define memory layout, management, instruction behavior and semantics, and optimally, be able to predict cache locality (arrays vs. linked-lists are the trivial but canonical example)

The moment the programming language, at any fundamental level, precludes me from defining how the machine should behave with respect to memory, semantics, or otherwise...it ceases to be a language that can be used for systems programming.

Disintermediating the meddling of C compilers is hard enough, languages like Go and Java are 'intractable' to say the least for actual systems programming.

Obj-C is only acceptable in the context of systems programming when you stop using everything that makes it Obj-C and just write C code.

I outlined additions/improvements that could be made to C and utilized in the context of systems (rather than applications) programming.

In a single sentence, it's about fundamentally about POWER and not "speed". That's why the desert-island language is C.


> There can be no limitations of any kind in terms of expressing to the machine, precisely how the machine should behave.

I hear what you're saying but you're overselling C here. Straight up ANSI C has a lot of limitations in telling the machine what to do. Even the various proprietary extensions have limitations right up until you stop writing anything that looks a little bit like C, e.g. you start using "asm" style intrinsics that let you do assembly inline.


>>In a single sentence, it's about fundamentally about POWER and not "speed".

Most code isn't inner loops in device drivers.

My point was that Obj C's behavior should be more or less deterministic, and method calling reasonably fast?

So "more or less" is just not good enough for you. [Edit: E.g. cache interaction is too hard to reason about when doing lookup for method dispatch, etc?]

Well, I'm too laid back to work on your problems. :-) I decided a long time ago that what I really liked most was to create lots of functionality in as short time as possible. But I admire people that care about things and learn about them relentlessly, so thanks for the information.


>I decided a long time ago that what I really liked most was to create lots of functionality in as short time as possible.

That's what I do now, but it's not what I've always done and I'm keenly aware of the limitations my peers are dealing with on a daily basis.


It seems most people don't really understand the core of systems programming. Let me try to summarize: There can be no limitations of any kind in terms of expressing to the machine, precisely how the machine should behave. Period. No ifs-ands-or-buts about it.

Actually it seems you don't understand that people mean different thing by "system's programming".

Not all system programming is about no-compromise, i.e as it would if it was only about driver or OS coding.

I'd trust Ken Thompson and Rob Pike to understand what system programming is better than some random dude on HN.


Chances with these 'random dudes on HN' are that they actually know a thing or two, I'd hate to make any assumptions there.

As for your 'what people mean by systems programming', how about you both stick to the definition/description used here:

http://en.wikipedia.org/wiki/System_programming

That would make it much easier to communicate. From the looks of it systems programming is all about no compromise, specifically for the reasons outlined by the GP. Now I wouldn't know him from Adam but even outside the realm of driver and OS programming there is plenty of room for software that is 100% deterministic in terms of time and space consumed.

Note that the 'alternate usage' term in the page linked above was specifically not what the GP was talking about if I understood it correctly.


You have it right and seems to understand systems programming and the consequences of the necessities underlying it perfectly.


>I'd trust Ken Thompson and Rob Pike to understand what system programming is better than some random dude on HN.

You'd be surprised, Pike has more or less retracted the "systems" moniker due to the reaction it got. He avoids the term now as a result.

I know this because I've been watching Go itself very closely.

But hey, it's just Rob Pike. Maybe ken still calls it a "systems" language. I'm still just a random dude on HN who thought plan9 was a fantastic idea and keeps track of Pike's work as a result :)


For all the talk of the speed benefits of Go, and it being static et all, I don't see much improvement over, say, Python.

A lot of the questions re speed bumps on the mailing list are answered with "those are microbenchmarks, what matters is real cases" and generally a "lalala hands in the ears approach", even when it's obvious that the problem is deeper than some microbenchmark only case.

Like this example:

https://groups.google.com/forum/?fromgroups#!topic/golang-nu...

[Downvote? Something very controversial about hashmap O behavior?]


You could compare python with perl or php, you could compare Go with C, C++ or Java.

But to compare Go to Python is a bit weird.

Of course, you could do it, but why would you, almost every metric that you'd want to use would be off. You're comparing a compiled language with lightweight threads aimed at just-above-low-level programming backed by a single vendor with an interpreted language that is mostly geared towards single threads of execution with a very high level of expressiveness that is developed by a bunch of open source gurus under the supervision of a benevolent dictator.


I think it's fine to compare Go and Python. They're both general-purpose programming languages. When choosing to write a new program, you can often pick either of them. I can imagine problems where either might be a reasonable choice. In fact, there are programs that I've written in both. (Granted, those were Project Euler exercises, not code that someone was paying me to write.)

Don't get too caught up in the marketing.


> I can imagine problems where either might be a reasonable choice.

Yes, I can imagine that too. But there are also a very large number of problems where either one is a (much) better fit, and it would seem to me that that is the majority of problems, not of the 'toy' variety.

The biggest factor in picking a language for a specific project is (in my opinion) availability of libraries and familiarity with the language by the team. Python scores very high for a large number of people in both those categories but it has been around for a while.

Go is backed by one of the largest software companies on the planet so it stands a chance but google has a bad rep when it comes to cutting off projects in mid stride.

The devil is always in the details with choices like these and without knowing more about a specific problem and the people that you intend to do the work with it is hard to say which one is the better fit beforehand.


For the type of applications people have been writing in Go, Python + PyPy would equally do as well.


Of course, you could do it, but why would you, almost every metric that you'd want to use would be off. You're comparing a compiled language with lightweight threads aimed at just-above-low-level programming backed by a single vendor with an interpreted language that is mostly geared towards single threads of execution with a very high level of expressiveness that is developed by a bunch of open source gurus under the supervision of a benevolent dictator.

The development model (benevolent dictator/backing company) does not have anything to do with the comparison. The license is also orthogonal. Not sure why you are adding those to the table.

The comparison I made is all about runtime behavior re: speed/memory usage here.

And, what I am saying is that despite Go being static and compiled and touted as "very fast", it's slower in a lot of respects to EVEN plain old Python, not to mention Java, which runs circles around it.

I'm not saying one would/should use Python and Go for the same tasks (though many people do, seeings as Go feels a little like a dynamic scripting language thanks to the easy syntax and the nice type system).

I'm saying "Hey, isn't the basic reason for someone to use Go over something like, say, Python, that it's supposed to be faster and with better memory handling? How does that play in practice?".


The conclusion of that thread was that his Python benchmark was accessing the hashmap's entries in sequential order (due to python's hash function being intentionally non-random), while the Go benchmark was accessing keys at random (since its hash function is random) and trashing the cache.



The title is wrong. It should be "Why I Don't Want to Learn Go and You Shouldn't Either"




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: