I didn't know this info, about the other compiler. That's great. Near the end of a project I'll try gccgo to see what performance difference it makes. The testing package makes profiling relatively easy.
Anyone have any insight as to how Go will avoid the garbage collection latency issues that arise in some situations with other GC languages, such as those that run on the JVM or CLR? I ask this in particular since Go is frequently mentioned as a C++ alternative.
Go's model is such that, compared to JVM-based languages, you have the control to create (much) less garbage in the first place, greatly reducing the size and impact of garbage collection pauses.
> Go's model is such that, compared to JVM-based languages, you have the control to create (much) less garbage in the first place, greatly reducing the size and impact of garbage collection pauses.
I have only heard of escape analysis (which Java has) and structs inside structs (which C# has; C# also lets you put structs on the stack). Is there anything that Go has over Java and C#?
In C#, it's up to the person defining the type to decide whether it has value/stack semantics (a struct) or not (a class). Structs have some limitations regarding constructors, and being passed by value is surprising to users used to classes. For these and other reasons, the vast majority of types are classes.
So you can have on-stack or embedded objects, but they are fairly rare.
In Go, the user of a type decides whether it will be used by reference (on the GC heap) or directly on the stack or embedded in an object: you can take a pointer to any type, or use the type directly.
That gives the consumer of a type much greater flexibility to not create garbage if they don't want to.
> In Go, the user of a type decides whether it will be used by reference (on the GC heap) or directly on the stack or embedded in an object: you can take a pointer to any type, or use the type directly.
Actually the distinction between heap and stack is not determined by how it is referenced. The compiler is free to stack-allocate any value as long as it does not escape the function. We can do this because pointers are opaque; there's no arithmetic.
The main point is that Go does not have classes. You just define methods on values. Values are no bigger than the data they represent, so you don't suffer from the same kinds of overheads seen in other "OOP"-centric languages.
A variable of an interface type is a pair consisting of a type descriptor and a concrete value. It is only when a concrete value of a statically known type is passed to something expecting an interface type that such a type tagged value is constructed.
Go lets you pass around raw values without overhead. An int32 is 4 bytes. A struct { a, b int32 } is eight bytes. A [4]int32 is 16 bytes. A [4]struct{ a, b int32 } is 32 bytes. (I think you get the point :-)
In Java all objects are passed by reference, which causes bloat and cache locality issues. Also there are bookkeeping costs associated with even trivial objects: a simple array carries around an additional 16 bytes of memory.
Furthermore, the core Java libraries make it very difficult to write code that doesn't generate a lot of garbage. In fact, it's very difficult to write allocation-efficient code in Java without writing very unidiomatic Java code. These problems are worsened in more dynamic JVM-based languages like Scala and Clojure, which generate huge amounts of garbage due to runtime reflection.
The topic of this discussion is garbage collection and memory allocation. The graphs on that page show Go beating Java in memory usage in every case. I'm not sure what your point is.
Scala is a statically typed language but it must do runtime type reflection to implement some of its features on top of the JVM. That comes at a cost (and in fact we decided not to implement Go on the JVM for this exact reason). I know of a certain well-known company that uses Scala heavily and their JVM instances spend >80% of their CPU time in garbage collection.
The JVM has had a tonne of optimization done to it. The Go compilers and runtime have had barely any. There's plenty of low-hanging fruit: recent changes to the gc code generation have yielded as much as 2x speedups in certain operations.
My observation, from watching very skilled Java programmers build and deploy programs, is that garbage generation and collection latency cause serious problems. My observation of similar Go programs is that these kinds of problems don't really come up.
> The graphs on that page show Go beating Java in memory usage in every case.
"Beating"? The JVM is configured to take as much available memory it thinks is necessary to speed up execution. Go lacks pretty much any runtime optimization and therefore doesn't do that.
> Scala is a statically typed language but it must do runtime type reflection to implement some of its features on top of the JVM. That comes at a cost (and in fact we decided not to implement Go on the JVM for this exact reason).
That's just non-sense. You take some (actually discouraged) corner cases of a completely different language to arrive at the decision to roll your own runtime (something the team seems to be completely unqualified for, judging the current state of the GC in Go?).
> My observation of similar Go programs is that these kinds of problems don't really come up.
Yes, because no one actually uses Go for anything where GC or latency would actually matter. Not even the garbage collection is working properly today. Please, show me some Go application server running with 128 GB heap doing something useful.
I don't think Go (or Dart) will have any mid- or long-term impact. The "OMG, we're at Google, we're so brilliant, let's design a language for all those stupid non-Google losers out there" approach to language design isn't working out so well, it seems.
Not even mentioning how seriously they messed up their "error" checking design. Confusing product with sum types ... god, you can't make that up.
IMO Go's standard library (http://golang.org/pkg/) is at least as complete as Python's for everyday programming and includes some things that Python's standard library doesn't such as crypto, image processing and a production ready HTTP server.
Right now I'd say Python has an advantage in comprehensive frameworks such as Django or Numpy but I think it's just a matter of time before similar frameworks emerge for Go.
An "alternative" doesn't mean "has to be as good or better at everything that C++ does".
Most programs don't have garbage collection latency issues. Look at Android or Windows Phone - all the user-level apps are written in garbage-collected language and they work just fine.
Look at web - all the interaction is written in JavaScript and Gmail works just fine.
At this point in the discussion people usually bring "real time" applications. Approximately no-one writes those applications.
Go is an alternative to C++ in the sense that many (but not all) programs that you had to write in C++ you can now write in Go.
Exactly - most programs don't generate all that much garbage. We've been working on GC for 40 years now, unless you're being reckless you probably won't notice it.
Despite the comparisons to C and C++, Go is not really a replacement for either of those languages. Each supports features that are not found in Go, and that are necessary for certain applications.
Go is more of a replacement for Python, Ruby, etc. The level of abstraction is very similar. The design of interfaces provides duck-typing. Obviously, Go is not exactly equivalent, but I find that Go is, in many ways, more similar to dynamic languages than it is to either C or C++.
This (among other topics) comes up frequently in Go discussions.
No one should say that Go is a replacement for C/C++ for all projects, however, it could be argued that most new, typical projects could be used with Go as opposed to C/C++/Python/etc.
There must be very few languages in the history of programming languages that could be considered complete replacements for others and that does not take anything away from those languages.
If you are thinking about writing operating systems, there are quite a few research operating system written in GC enabled languages as proof of concept.
If you are talking about the amount of control over the machine, or the set of abstractions available to the programmer, then I fully agree with you.
I've been dealing with this in quite a bit of detail in the last week. The answer is: it is entirely possible to write a Go program (or sub-programs, which is even better: use GC when you need it) that produces absolutely no garbage, and it doesn't require being a seer to do so. It requires a bit more seer-ness to leverage the fairly simpleminded escape analysis to make some things more terse, but that's a fairly small workflow optimization.
The biggest hurdle I've had is that the standard library can make it difficult to avoid allocation: for example, I want to re-initialize a "bytes.Reader" or "bytes.Buffer", but I can't just pass a new slice and reset the data structure fields, from what I know. As a result, I've had to do the somewhat unpleasant task of pulling in standard library files and then tweaking them, or writing new abstractions to do some low level stuff entirely -- perhaps unavoidable, it is probably better to have a nice interface for general cases from a standard library perspective.
It is worse when you realize that a standard library function calls "make" in a place where it'll be in your inner loop: you really wish you could pass the memory to scribble into instead.
Another surprisingly expensive thing is the dynamic dispatch on interfaces. This is easy to avoid if one just writes a specialized version of a function accepting all the concrete types in the common case, though. Beyond that, memory copying, something I've found that the bytes.Buffer and bytes.Reader make hard to avoid while still capturing their useful semantics.
All in all: more pleasant than C for most projects, and very nearly as fast when like this generally, so even if you end up having to write a good chunk of stuff yourself you are no worse off than if you had chosen C to begin with.
A very notable caveat: you can't handle in any way (afaik) failed requests for virtual memory, which is rather a killer for some kind of programs. This one makes me a bit annoyed, but I can see why it's difficult to address. That doesn't make me feel much better, though.
To give a sense of what I'm doing: I'm parsing very small messages (minimum: 5 bytes, and often quite small, a common pathological case would be a handful more bytes) and passing them on with no interesting processing, and trying to get this to be fast in the trivial case. This is the Postgres wire protocol. So far, Postgres is still beating the crap out of me, which is annoying considering it actually has to do some work, and I'm just inspecting one byte and one 4-byte word of the message and then passing it on. At this point, with two copies the program is ~20% runtime.memmove, so the next high pole is to eliminate one of the copies.
The original work ongccgo was done by Ian Lance Taylor(of the gold linker fame) who works at Google, and now is being accepted and supported by the GCC project.
Go feels to me like it is trying to combine C and Python. Much more efficient than Python, but not as efficient as C. Much more expressive than C, but not as expressive as Python. I can't quite decide if that's combining the best of both worlds, or compromising on both fronts.
What's up with the official Go binaries being incompatible with RHEL 5? I might have another look in about a decade or so.
> What's up with the official Go binaries being incompatible with RHEL 5? I might have another look in about a decade or so.
Go runs on RHEL 5.2 and above (released in May 2008, and there have been 7 further point releases since). If you REALLY want to run it on 5.1 and have gcc then you can build your own Go tool chain in about 2 minutes.
Your whole post is FUD. You don't know anything about Go yet offer a negative assessment. Why bother?
If I wasn't interested in Go I wouldn't complain about not having binaries. You may not be running RHEL 5.0 but there are many organizations which still have many systems on it. It's not always up to Joe Developer to decide to upgrade the OS on every box in an organization. Perhaps I need to know more about building go to compile my own binaries, but not having to deal with C is one of the reason's I was looking at Go in the first place.
How is this FUD? C is faster than Go, Python takes less code than Go and the binaries don't support RHEL 5.0. I thought my post wasn't particularly biased, but I'm pretty shocked at the reaction I got :(
you seem to be presenting a false dichotomy. can't go be a success in some place in between c and python?
my haskell is faster than python and more expressive. therefore you should stop using python immediately, right? of course not, because anyone using the shooutout to make sweeping generalizations has of course read the massive disclaimer warning against that...
Go does fall somewhere between the two, which is what I was getting at. Whether that's a good or a bad thing was what I hadn't made my mind up about. I like the idea of something that's expressive and fast, my thoughts are currently that it could to be more expressive.
So Google Go programs won't run on any RHEL or Fedora with SELinux enabled. Requiring users to disable SELinux in order to run programs is just insane... even a lax SELinux like the default policy from Red Hat is still very effective.
Whoever thought an executable stack was a good idea... well they certainly don't have any clue about OS security.
enneff: his post is FUD and you are right and on every Go thread here, there are always some people to needlessly bash it. And while I appreciate your frankness as a developer advocate for Go, I think your points would go over more smoothly if you weren't so defensive about it. I notice you have been a bit curt with the criticisms.
I like Go, and I have also seen that nearly all people who actually get to the step of writing Go code also like it. It doesn't look too good on paper (compared to Clojure etc) but it works really well in practice and that's awesome.
Learning a new language is an investment and by investing (or not investing) you have made a commitment to that choice. People usually continue to justify/rationalize that decision long after the original choice.
Although your post may not be considered "spreading misinformation", it seems like an "attempt to influence perception by disseminating negative and dubious [...] information".
The bottom line is that people who have committed effort into Go/Clojure/Scala/etc tend justify it by hyping it up a bit. Those that decided to not commit any effort (or commit effort in a different/competing language) tend to justify their choice by bashing the language publicly. If you decided to ignore Go and stick with C/C++/Java/Python, fine, that's your prerogative. But why come to a thread about it and post about how you are going to ignore it? Do you want others to ignore it as well? Why? The truth is you probably didn't consciously decide to do it. But it happens all of the time in discussions online and offline.
The Misconception: You make rational decisions based on
the future value of objects, investments and experiences.
The Truth: Your decisions are tainted by the emotional
investments you accumulate, and the more you invest in
something the harder it becomes to abandon it.
You're right, I could have been more even handed. I just get frustrated when people bring nothing but negativity, seemingly for negativity's sake alone. I should just respond on a purely factual level, but sometimes it's hard.
> Go feels to me like it is trying to combine C and Python.
I think that's accurate, and to me it's a great thing.
I'm currently converting many functions written in Python, to Go. I haven't coded in Python or studied it, but I can read it fine. This exercise has made me a lot more interested in Python! However, I'm confident that for my use case the runtime speed of Go will pay off, even though it's not nearly as simple to code in as Python from the looks of it. I'll use Python (or even PHP) for things where speed isn't such an issue.
Go feels to me like it is trying to combine C and Python...
That sounds about right. From the Go FAQ: Go is an attempt to combine the ease of programming of an interpreted, dynamically typed language with the efficiency and safety of a statically typed, compiled language.
Of course, whether the precise balance that Go comes to works for you is personal. I really like having most of the efficiency of C and much of the expressiveness of Ruby. I'm just getting started, but I haven't had this much fun learning a new language since I learned Ruby six years ago. Go is differently expressive than Ruby and introduces (to me) some powerful, interesting, and fun ideas (goroutines plus channels, for example.)
I think Ruby will still be my go-to language for everyday tasks, but Go definitely looks like it will have its place in my toolbox, likely replacing my occasional use of C++ at the very least. I also plan to use it on App Engine.
I don't think your post was FUD, but I'm guessing it was "I might have another look in about a decade or so" that might have felt dismissive to some people. That's not FUD, though, and it's fair to express your personal opinion like that.
49 comments
[ 3.8 ms ] story [ 104 ms ] threadI have only heard of escape analysis (which Java has) and structs inside structs (which C# has; C# also lets you put structs on the stack). Is there anything that Go has over Java and C#?
So you can have on-stack or embedded objects, but they are fairly rare.
In Go, the user of a type decides whether it will be used by reference (on the GC heap) or directly on the stack or embedded in an object: you can take a pointer to any type, or use the type directly.
That gives the consumer of a type much greater flexibility to not create garbage if they don't want to.
Actually the distinction between heap and stack is not determined by how it is referenced. The compiler is free to stack-allocate any value as long as it does not escape the function. We can do this because pointers are opaque; there's no arithmetic.
The main point is that Go does not have classes. You just define methods on values. Values are no bigger than the data they represent, so you don't suffer from the same kinds of overheads seen in other "OOP"-centric languages.
For normal values you don't need it, because Go is statically typed. The compiler knows where the method is.
In Java all objects are passed by reference, which causes bloat and cache locality issues. Also there are bookkeeping costs associated with even trivial objects: a simple array carries around an additional 16 bytes of memory.
Furthermore, the core Java libraries make it very difficult to write code that doesn't generate a lot of garbage. In fact, it's very difficult to write allocation-efficient code in Java without writing very unidiomatic Java code. These problems are worsened in more dynamic JVM-based languages like Scala and Clojure, which generate huge amounts of garbage due to runtime reflection.
Here's an interesting discussion of these issues:
http://loadcode.blogspot.com/2009/12/go-vs-java.html
Scala is a statically typed language
Go may make more efficient use of memory for the cases you describe, but the JVM still beats the pants off Go:
http://shootout.alioth.debian.org/u64q/benchmark.php?test=al...
Also, you haven't factored in Java's escape analysis and on-stack allocation.
Scala is a statically typed language but it must do runtime type reflection to implement some of its features on top of the JVM. That comes at a cost (and in fact we decided not to implement Go on the JVM for this exact reason). I know of a certain well-known company that uses Scala heavily and their JVM instances spend >80% of their CPU time in garbage collection.
The JVM has had a tonne of optimization done to it. The Go compilers and runtime have had barely any. There's plenty of low-hanging fruit: recent changes to the gc code generation have yielded as much as 2x speedups in certain operations.
My observation, from watching very skilled Java programmers build and deploy programs, is that garbage generation and collection latency cause serious problems. My observation of similar Go programs is that these kinds of problems don't really come up.
"Beating"? The JVM is configured to take as much available memory it thinks is necessary to speed up execution. Go lacks pretty much any runtime optimization and therefore doesn't do that.
> Scala is a statically typed language but it must do runtime type reflection to implement some of its features on top of the JVM. That comes at a cost (and in fact we decided not to implement Go on the JVM for this exact reason).
That's just non-sense. You take some (actually discouraged) corner cases of a completely different language to arrive at the decision to roll your own runtime (something the team seems to be completely unqualified for, judging the current state of the GC in Go?).
> My observation of similar Go programs is that these kinds of problems don't really come up.
Yes, because no one actually uses Go for anything where GC or latency would actually matter. Not even the garbage collection is working properly today. Please, show me some Go application server running with 128 GB heap doing something useful.
I don't think Go (or Dart) will have any mid- or long-term impact. The "OMG, we're at Google, we're so brilliant, let's design a language for all those stupid non-Google losers out there" approach to language design isn't working out so well, it seems.
Not even mentioning how seriously they messed up their "error" checking design. Confusing product with sum types ... god, you can't make that up.
Does that rely on heuristics like escape analysis or is it user defined (and predictable)?
Right now I'd say Python has an advantage in comprehensive frameworks such as Django or Numpy but I think it's just a matter of time before similar frameworks emerge for Go.
Most programs don't have garbage collection latency issues. Look at Android or Windows Phone - all the user-level apps are written in garbage-collected language and they work just fine.
Look at web - all the interaction is written in JavaScript and Gmail works just fine.
At this point in the discussion people usually bring "real time" applications. Approximately no-one writes those applications.
Go is an alternative to C++ in the sense that many (but not all) programs that you had to write in C++ you can now write in Go.
Aren't there people blaming Android's perceived laggyness on this?
Another thing is that many developers do too much in the UI thread instead of doing it in the background or asynchronously.
Go is more of a replacement for Python, Ruby, etc. The level of abstraction is very similar. The design of interfaces provides duck-typing. Obviously, Go is not exactly equivalent, but I find that Go is, in many ways, more similar to dynamic languages than it is to either C or C++.
No one should say that Go is a replacement for C/C++ for all projects, however, it could be argued that most new, typical projects could be used with Go as opposed to C/C++/Python/etc.
There must be very few languages in the history of programming languages that could be considered complete replacements for others and that does not take anything away from those languages.
If you are thinking about writing operating systems, there are quite a few research operating system written in GC enabled languages as proof of concept.
If you are talking about the amount of control over the machine, or the set of abstractions available to the programmer, then I fully agree with you.
D or Rust would be a better choice, eventually.
The biggest hurdle I've had is that the standard library can make it difficult to avoid allocation: for example, I want to re-initialize a "bytes.Reader" or "bytes.Buffer", but I can't just pass a new slice and reset the data structure fields, from what I know. As a result, I've had to do the somewhat unpleasant task of pulling in standard library files and then tweaking them, or writing new abstractions to do some low level stuff entirely -- perhaps unavoidable, it is probably better to have a nice interface for general cases from a standard library perspective.
It is worse when you realize that a standard library function calls "make" in a place where it'll be in your inner loop: you really wish you could pass the memory to scribble into instead.
Another surprisingly expensive thing is the dynamic dispatch on interfaces. This is easy to avoid if one just writes a specialized version of a function accepting all the concrete types in the common case, though. Beyond that, memory copying, something I've found that the bytes.Buffer and bytes.Reader make hard to avoid while still capturing their useful semantics.
All in all: more pleasant than C for most projects, and very nearly as fast when like this generally, so even if you end up having to write a good chunk of stuff yourself you are no worse off than if you had chosen C to begin with.
A very notable caveat: you can't handle in any way (afaik) failed requests for virtual memory, which is rather a killer for some kind of programs. This one makes me a bit annoyed, but I can see why it's difficult to address. That doesn't make me feel much better, though.
To give a sense of what I'm doing: I'm parsing very small messages (minimum: 5 bytes, and often quite small, a common pathological case would be a handful more bytes) and passing them on with no interesting processing, and trying to get this to be fast in the trivial case. This is the Postgres wire protocol. So far, Postgres is still beating the crap out of me, which is annoying considering it actually has to do some work, and I'm just inspecting one byte and one 4-byte word of the message and then passing it on. At this point, with two copies the program is ~20% runtime.memmove, so the next high pole is to eliminate one of the copies.
So the answer to your question is: both.
What's up with the official Go binaries being incompatible with RHEL 5? I might have another look in about a decade or so.
Go runs on RHEL 5.2 and above (released in May 2008, and there have been 7 further point releases since). If you REALLY want to run it on 5.1 and have gcc then you can build your own Go tool chain in about 2 minutes.
Your whole post is FUD. You don't know anything about Go yet offer a negative assessment. Why bother?
http://shootout.alioth.debian.org/u32/benchmark.php?test=all...
Fact: Python is more expressive than Go (less code):
http://shootout.alioth.debian.org/u32/benchmark.php?test=all...
If I wasn't interested in Go I wouldn't complain about not having binaries. You may not be running RHEL 5.0 but there are many organizations which still have many systems on it. It's not always up to Joe Developer to decide to upgrade the OS on every box in an organization. Perhaps I need to know more about building go to compile my own binaries, but not having to deal with C is one of the reason's I was looking at Go in the first place.
How is this FUD? C is faster than Go, Python takes less code than Go and the binaries don't support RHEL 5.0. I thought my post wasn't particularly biased, but I'm pretty shocked at the reaction I got :(
my haskell is faster than python and more expressive. therefore you should stop using python immediately, right? of course not, because anyone using the shooutout to make sweeping generalizations has of course read the massive disclaimer warning against that...
http://code.google.com/p/go/issues/detail?id=47
So Google Go programs won't run on any RHEL or Fedora with SELinux enabled. Requiring users to disable SELinux in order to run programs is just insane... even a lax SELinux like the default policy from Red Hat is still very effective.
Whoever thought an executable stack was a good idea... well they certainly don't have any clue about OS security.
I like Go, and I have also seen that nearly all people who actually get to the step of writing Go code also like it. It doesn't look too good on paper (compared to Clojure etc) but it works really well in practice and that's awesome.
As I have pointed out everything in my post was factually accurate. I had no intention of spreading misinformation.
Although your post may not be considered "spreading misinformation", it seems like an "attempt to influence perception by disseminating negative and dubious [...] information".
The bottom line is that people who have committed effort into Go/Clojure/Scala/etc tend justify it by hyping it up a bit. Those that decided to not commit any effort (or commit effort in a different/competing language) tend to justify their choice by bashing the language publicly. If you decided to ignore Go and stick with C/C++/Java/Python, fine, that's your prerogative. But why come to a thread about it and post about how you are going to ignore it? Do you want others to ignore it as well? Why? The truth is you probably didn't consciously decide to do it. But it happens all of the time in discussions online and offline.
more info:
https://en.wikipedia.org/wiki/Confirmation_bias tendency of people to favor information that confirms their beliefs or hypotheses
https://en.wikipedia.org/wiki/Post-purchase_rationalization someone who purchases an expensive product or service overlooks any faults or defects in order to justify their purchase.
and my favorite: http://youarenotsosmart.com/2011/03/25/the-sunk-cost-fallacy...
I think that's accurate, and to me it's a great thing.
I'm currently converting many functions written in Python, to Go. I haven't coded in Python or studied it, but I can read it fine. This exercise has made me a lot more interested in Python! However, I'm confident that for my use case the runtime speed of Go will pay off, even though it's not nearly as simple to code in as Python from the looks of it. I'll use Python (or even PHP) for things where speed isn't such an issue.
That sounds about right. From the Go FAQ: Go is an attempt to combine the ease of programming of an interpreted, dynamically typed language with the efficiency and safety of a statically typed, compiled language.
Of course, whether the precise balance that Go comes to works for you is personal. I really like having most of the efficiency of C and much of the expressiveness of Ruby. I'm just getting started, but I haven't had this much fun learning a new language since I learned Ruby six years ago. Go is differently expressive than Ruby and introduces (to me) some powerful, interesting, and fun ideas (goroutines plus channels, for example.)
I think Ruby will still be my go-to language for everyday tasks, but Go definitely looks like it will have its place in my toolbox, likely replacing my occasional use of C++ at the very least. I also plan to use it on App Engine.
I don't think your post was FUD, but I'm guessing it was "I might have another look in about a decade or so" that might have felt dismissive to some people. That's not FUD, though, and it's fair to express your personal opinion like that.
Same here. I love having speed closer to C that's way easier to code than C.
Andrew Wilkins has written llgo, a compiler for Go, written in Go, and using the LLVM compiler infrastructure: https://github.com/axw/llgo/#readme