A review of Go

1,186 views
Skip to first unread message

Jörg Walter

unread,
Jun 7, 2011, 6:31:05 PM6/7/11
to golan...@googlegroups.com

Hello Go enthusiasts,


As part of familiarizing myself with Go, I stumbled over lots of questions, criticism and whatnot. While writing all that down and backing it up with some research, it transformed into a thorough review and introduction into Go, aimed at seasoned programmers that are new to Go. You might find this interesting. I certainly learned a lot about Go while writing it. I'd appreciate corrections and feedback, especially on the "open questions" section at the end. I will update the document with all insights I gain here.


http://www.syntax-k.de/projekte/go-review


I'm now porting one of the apps I maintain to Go. Keep up the good work!


--

Cheers,

Jörg

Kyle Consalus

unread,
Jun 7, 2011, 6:41:28 PM6/7/11
to Jörg Walter, golan...@googlegroups.com
Your review seems to say that in Go you must (or should) have one file per package.
This is not the case. Multi-file packages are common.
It is true that multi-package files aren't allowed.

Scott Lawrence

unread,
Jun 7, 2011, 6:43:26 PM6/7/11
to golan...@googlegroups.com
On 06/07/2011 06:41 PM, Kyle Consalus wrote:
> This is not the case. Multi-file packages are common.

(In particular, in the go standard library, almost all (if not all)
packages have multiple files.)

signature.asc

Jörg Walter

unread,
Jun 7, 2011, 7:15:57 PM6/7/11
to golan...@googlegroups.com

On Middeweken, de 8. Juni 2011, Kyle Consalus wrote:

> Your review seems to say that in Go you must (or should) have one file

> per package.

> This is not the case. Multi-file packages are common.

> It is true that multi-package files aren't allowed.


Oh, thanks for the correction. I now discovered the FAQ entry. I will correct that.


--

Cheers,

Jörg

jimmy frasche

unread,
Jun 7, 2011, 8:02:54 PM6/7/11
to Jörg Walter, golan...@googlegroups.com
You should note that the rules of semicolon insertion are somewhat
less convoluted and brittle than javascripts.

The Parens aren't optional, per se. They're unnecessary. You can
include them but only where you could use them with an expression,
that is:

for(i := 0; i < 10; i++) {}

is a syntax error.

In the implict declarations section it's probably overly confusing to
have the type of the return value be the name of the function
returning it, something like "var foo Baz = Bar(1, 2, 3)" would keep
it reading like a constructor for people unfamiliar with Go's lack of
them.

For variable declaration being backwards, it's probably better to show
the difference between "var a, b *int" in Go and "int* a, b;" in C.

range isn't a function. It's purely a syntactic artifact used to
signal that it's a 'for each' style loop.

There's no dynamic loading, but I believe that's on the roadmap.

> How high is the memory overhead of interfaces?

http://research.swtch.com/2009/12/go-data-structures-interfaces.html

As far as structs and arrays they take up the space you tell them to
and no more.

You can only define methods on types you create in the current
package. It makes the compiler's job way easier, but more importantly
it makes the reader of your code's job easier—which is one of my
favorite things about Go :)

You cannot add methods to interfaces.

Go is less than 2 years old (well since it's initial public release,
anyway). It's a baby. Precocious lad, though.

Excellent write up. Thank you for taking the time. I'm sure others
will find it very useful.

Paul Samways

unread,
Jun 7, 2011, 9:39:04 PM6/7/11
to Jörg Walter, golan...@googlegroups.com
That was a great read, thanks Jörg :)

"At best, there would be a community proposal process (like Python,
Java, Perl6, XMPP, etc. have) which tracks these suggestions, outlines
requirements that must be fulfilled for a given proposal to be
seriously considered, and summarizes the current state of development.
Then, ideas can mature, can be rejected with comprehensible arguments,
can be replaced by even better ideas, and finally make it into the
language without compromising its design goals."

This is something I'd love to see as well.

Russ Cox

unread,
Jun 7, 2011, 10:30:10 PM6/7/11
to Jörg Walter, golang-nuts
Jörg,

Nice doc. Thanks for taking the time to write it.

> like range().

range is a keyword, not a function. Parens after it are unnecessary
in prose and almost always in code too.

> Unfortunately, Duck Typing is incomplete. Imagine an interface like this: ...

That doesn't work because the memory layout of a MyObj
is different from the memory layout of an Arithmetic.
Other languages struggle mightily with this even when
the memory layouts match. Go just says no.

> I am not sure if I am happy with that pointer/value business.
> The all-things-are-references semantics of Java are much simpler.

That's true, but in return for having values you get more fine-grained
control over memory layout. See the beginning of this post,
before the first section heading:
http://loadcode.blogspot.com/2009/12/go-vs-java.html

> Does inlining work? How could cross-package inlining work?

It doesn't work yet but it is on the short list of compiler work.
Cross-package inlining can work because the import reads
compiler output, so the compiler can leave information for
itself to use when importing the package.

> Would it be possible to make Go 8-bit capable?
> C scales down to 8-bit microcontrollers. What is the minimum
> hardware a (possibly limited) Go runtime can work?

Go requires that int be at least 32 bits and that int64 and uint64 be
supplied; practically that means we've given up on 8- and 16-bit CPUs.

> Can Go object files be loaded at runtime?
> Do types implemented in these files integrate
> seamlessly into the hosting application?

They can't. There's no fundamental reason, just that we
started with fully-static linking and that simplifies a variety
of things.

> What are the limitations of the optimizer?
> Assuming gccgo, does it leverage a similar level of
> optimization as when compiling C++, or are significant
> steps unsuported?

For 6g and 8g, it does basic registerization, some
strength reduction, and trivial bounds check elimination.
Basic inlining and escape analysis (both cross-package)
have concrete plans and are likely before too long.
The most glaring things missing are some better constant
and condition propagation in order to remove more bounds
checks. None of this is fundamental, it's just not there yet.
It's important to remember that unlike most of the languages
it gets compared to, there are tons of open opportunities for
making Go run faster and smaller.

> Would it be possible to detect integer overflows, another
> well-known security defect? With operator overloading,
> I guess it would be easy to implement a guarded data type.

It's not possible in the language as it stands today, because
Go (unlike C) defines integer operations to wrap around.
There is no undefined behavior on overflow.

> How high is the memory overhead of interfaces? Of structs? Of arrays?

http://research.swtch.com/2009/11/go-data-structures.html
http://research.swtch.com/2009/12/go-data-structures-interfaces.html
http://blog.golang.org/2011/01/go-slices-usage-and-internals.html

> How high is the CPU time overhead of an interface method dispatch?

It's a vtable call, just like a C++ virtual function call.

> Of creating a goroutine?

It's a memory allocation.

> Of scheduling goroutines?

It's a few lock operations. The scheduler is a trivial round-robin
so it can make some dumb decisions, but it will improve.

> Is it possible to add methods to types not declared in the
> current package? Maybe even to int64?

No. No, unless you define your own type, as you did
with Handler in the write-up.

> Is it possible to add Methods to interfaces, i.e. a method that has
> the interface as receiver and thus is the same for all objects
> implementing that interface?

No, but you can write a function that takes one of those
interface values as a parameter. Allowing methods on interfaces
would complicate the decisions about what methods a particular
value has, especially since most values satisfy an interface
implicitly.

Russ

John Pritchard

unread,
Jun 8, 2011, 3:08:01 AM6/8/11
to golang-nuts


So the analytical view is of a pointer and reference syntax and semantics with a special case inserted for the value of types beyond machine words.

This special case obscures part of the reference syntax for the value syntax and semantics, which includes implicit copy operations.

chris dollin

unread,
Jun 8, 2011, 3:15:02 AM6/8/11
to John Pritchard, golang-nuts
On 8 June 2011 08:08, John Pritchard <john.dougla...@gmail.com> wrote:
>
>
> So the analytical view is of a pointer and reference syntax and semantics
> with a special case inserted for the value of types beyond machine words.
> This special case obscures part of the reference syntax for the value syntax
> and semantics, which includes implicit copy operations.

Could you unpack that a little?

Chris

--
Chris "allusive" Dollin

John Pritchard

unread,
Jun 8, 2011, 3:25:12 AM6/8/11
to chris dollin, golang-nuts
Sure.. the syntax and semantics of Go could be described as the syntax and semantics of pointers and references (for extended or complex types larger than a machine word); plus the special case of the syntax and semantics of a value of a struct.

John

Russ Cox

unread,
Jun 8, 2011, 8:07:13 AM6/8/11
to John Pritchard, chris dollin, golang-nuts
> Sure.. the syntax and semantics of Go could be described as the syntax and
> semantics of pointers and references (for extended or complex types larger
> than a machine word); plus the special case of the syntax and semantics of a
> value of a struct.

I think you have it backward. The part about types larger
than a machine word only applies to interface values.
They are the special case.

Russ

Miguel Pignatelli

unread,
Jun 8, 2011, 10:56:15 AM6/8/11
to golan...@googlegroups.com
Although it is a bit annoying sometimes, I like that go complains about
variables (and packages) declared and not used. It "forces" me the habit
to write cleaner code.
But why this doesn't happen in function parameters?

func test (param1 int) {
return
}

And related to this. I found a couple of situations where a declared
variables are not needed. For example while bechmarking a function call
(and the result of the function is not used anymore) or debugging. What
is the best way of avoiding this error?
Currently I am using something like:

res := foo()
if res == nil {}

or a similar comparison depending on the type of "res".

M;

mikespook

unread,
Jun 8, 2011, 10:59:28 AM6/8/11
to golan...@googlegroups.com
There is some really useful information, especially in the "rant" part with the c-oid languages. ;)

I've translated this review into Chinese with out your permit. Hope you don't mind that.

Here is the Chinese version: http://www.mikespook.com/2011/06/go%e7%bc%96%e7%a8%8b%e8%af%ad%e8%a8%801/

John Asmuth

unread,
Jun 8, 2011, 11:00:00 AM6/8/11
to golan...@googlegroups.com


On Wednesday, June 8, 2011 10:56:15 AM UTC-4, M; wrote:
Although it is a bit annoying sometimes, I like that go complains about
variables (and packages) declared and not used. It "forces" me the habit
to write cleaner code.
But why this doesn't happen in function parameters?

func test (param1 int) {
return
}

That would make it irritating to make a type satisfy an interface, or in general have a function that must have a specific signature with behavior that doesn't necessarily depend on all of the parameters. 

And related to this. I found a couple of situations where a declared
variables are not needed. For example while bechmarking a function call
(and the result of the function is not used anymore) or debugging. What
is the best way of avoiding this error?
Currently I am using something like:


var x int
_ = x

if a variable is on a RHS, it won't generate the complaint. And this particular operation gets compiled into oblivion, I think. Either way it's the standard.

Matt Kane's Brain

unread,
Jun 8, 2011, 11:03:08 AM6/8/11
to golan...@googlegroups.com
On Wed, Jun 8, 2011 at 11:00, John Asmuth <jas...@gmail.com> wrote:
>
>
> On Wednesday, June 8, 2011 10:56:15 AM UTC-4, M; wrote:
>>
>> Although it is a bit annoying sometimes, I like that go complains about
>> variables (and packages) declared and not used. It "forces" me the habit
>> to write cleaner code.
>> But why this doesn't happen in function parameters?
>>
>> func test (param1 int) {
>> return
>> }
>
> That would make it irritating to make a type satisfy an interface, or in
> general have a function that must have a specific signature with behavior
> that doesn't necessarily depend on all of the parameters.

Not that annoying. Just use _ as the names of params you don't care about.

--
matt kane's brain
http://hydrogenproject.com
capoeira in boston http://capoeirageraisboston.com
aim -> mkbatwerk ; skype/y! -> mkb218 ; gtalk -> mkb.dirtyorg

roger peppe

unread,
Jun 8, 2011, 11:09:27 AM6/8/11
to Miguel Pignatelli, golan...@googlegroups.com
On 8 June 2011 15:56, Miguel Pignatelli <miguel.p...@uv.es> wrote:
> Although it is a bit annoying sometimes, I like that go complains about
> variables (and packages) declared and not used. It "forces" me the habit to
> write cleaner code.
> But why this doesn't happen in function parameters?
>
> func test (param1 int) {
>        return
> }

i think part of the reason is that function parameters can be
visible in externally visible documentation - it's useful to be
able to name them even if they're not used.

Miguel Pignatelli

unread,
Jun 8, 2011, 11:13:50 AM6/8/11
to roger peppe, golan...@googlegroups.com

Hmmm... and why do you want to document parameters that are not used in
the function? For me, such documentation is buggy.

M;

Miguel Pignatelli

unread,
Jun 8, 2011, 11:19:34 AM6/8/11
to golan...@googlegroups.com
On 08/06/11 16:03, Matt Kane's Brain wrote:
> On Wed, Jun 8, 2011 at 11:00, John Asmuth<jas...@gmail.com> wrote:
>>
>>
>> On Wednesday, June 8, 2011 10:56:15 AM UTC-4, M; wrote:
>>>
>>> Although it is a bit annoying sometimes, I like that go complains about
>>> variables (and packages) declared and not used. It "forces" me the habit
>>> to write cleaner code.
>>> But why this doesn't happen in function parameters?
>>>
>>> func test (param1 int) {
>>> return
>>> }
>>
>> That would make it irritating to make a type satisfy an interface, or in
>> general have a function that must have a specific signature with behavior
>> that doesn't necessarily depend on all of the parameters.
>
> Not that annoying. Just use _ as the names of params you don't care about.
>

Yes, you are right. This is valid:

func test () int {
return 1
}

func main () {
_ = test()
}

And this answers my second question.

Thx,

M;

Jan Mercl

unread,
Jun 8, 2011, 11:29:41 AM6/8/11
to golan...@googlegroups.com, roger peppe
On Wednesday, June 8, 2011 5:13:50 PM UTC+2, M; wrote:

Hmmm... and why do you want to document parameters that are not used in
the function? For me, such documentation is buggy.

Not necessarily. E.g. in a method satisfying some interface the concrete implementation may have no use for some of some of the arguments (due to that concrete implementation). Or the argument only adjusts some behaviour and this is supposed to be implemented only later (or never :-)

Jan Mercl

unread,
Jun 8, 2011, 11:32:54 AM6/8/11
to golan...@googlegroups.com
On Wednesday, June 8, 2011 4:59:28 PM UTC+2, mikespook wrote:
I've translated this review into Chinese with out your permit. Hope you don't mind that.

The original article includes a license which doesn't require a pesmission while you comply with that license (which I hope is the case):

Miguel Pignatelli

unread,
Jun 8, 2011, 11:37:34 AM6/8/11
to golan...@googlegroups.com

Ok, the former could be a common case.

Thanks,

M;

Ian Lance Taylor

unread,
Jun 8, 2011, 11:49:06 AM6/8/11
to Miguel Pignatelli, golan...@googlegroups.com
Miguel Pignatelli <miguel.p...@uv.es> writes:

> Although it is a bit annoying sometimes, I like that go complains
> about variables (and packages) declared and not used. It "forces" me
> the habit to write cleaner code.
> But why this doesn't happen in function parameters?
>
> func test (param1 int) {
> return
> }

An unused variable is probably a bug. An unused package is a dependency
you can clean up. An unused parameter doesn't really indicate a bug or
a dependency issue. If the function exists to implement an interface,
then an unused parameter is entirely normal.


> And related to this. I found a couple of situations where a declared
> variables are not needed. For example while bechmarking a function
> call (and the result of the function is not used anymore) or
> debugging. What is the best way of avoiding this error?
> Currently I am using something like:
>
> res := foo()
> if res == nil {}
>
> or a similar comparison depending on the type of "res".

For this example I would just write
foo()
More generally, use
_ = res

Ian

John Pritchard

unread,
Jun 8, 2011, 1:15:42 PM6/8/11
to golang-nuts

Russ,

There's a value of struct syntax with implicit copy on assignment?  And pass by value is a reference to a copy?  (The only way to avoid copies is via pointer syntax?  interface syntax?)

I must have misunderstood something in my off hours reading.

This is the primary cause of my thinking that reference syntax and semantics have been truncated in an awkward way.  

John

chris dollin

unread,
Jun 8, 2011, 1:34:16 PM6/8/11
to John Pritchard, golang-nuts
On 8 June 2011 18:15, John Pritchard <john.dougla...@gmail.com> wrote:
>
> Russ,
> There's a value of struct syntax with implicit copy on assignment?

I don't understand.

You can copy struct values happily so long as they either
have no unexported fields or you're in the struct-defining package.

>  And pass by value is a reference to a copy?

Pass by value is pass by value, ie, a copy of whatever it is
you're passing, be it a struct or not. Of course, if the value
is (or contains) a pointer, the pointer (but not the pointee) is
copied, which is how maps & slices have the effect they do:
they're fat pointers.

If you pass a non-interface value to an interface variable,
then that value gets copied.

 (The only way to avoid copies is via
> pointer syntax?  interface syntax?)

The way to pass things by reference is to pass pointers
to them. This avoids copying the thing at the cost of
copying a pointer instead.

There's a tricky bit of implicit referencing that goes on
when x.f(y) calls a method f defined on a pointer type but
x is a variable of the pointed-to type: its address is
implicitly taken.


> I must have misunderstood something in my off hours reading.
> This is the primary cause of my thinking that reference syntax and semantics
> have been truncated in an awkward way.

I still don't understand what this means. Example?

Steven

unread,
Jun 8, 2011, 1:43:34 PM6/8/11
to John Pritchard, golang-nuts
On Wednesday, June 8, 2011, John Pritchard
<john.dougla...@gmail.com> wrote:
>
> Russ,
> There's a value of struct syntax with implicit copy on assignment?  And pass by value is a reference to a copy?  (The only way to avoid copies is via pointer syntax?  interface syntax?)

>
>
> I must have misunderstood something in my off hours reading.
> This is the primary cause of my thinking that reference syntax and semantics have been truncated in an awkward way.
>
>
> John

There is no implicit copy on assignment. All assignments create
copies. Everything in Go is a value. There are no reference semantics.
Some values are reference values by virtue of referring to data which
is shared by all copies of that value. A pointer is a value that
refers to a single other value of a specific type. If you pass around
or assign a struct{X, Y int}, then this value is copied each time. If
you pass around or assign a *struct{X, Y int}, then the pointer
(reference) is copied, but whatever it refers to is not. Slices, maps,
and channels are also reference values with different properties from
pointers.

An interface variable can store values of any type that satisfies the
interface. Semantically, the thing inside the interface is copied and
passed around just like it would be if it weren't in the interface.
However, interfaces are implemented as having a fixed size. If the
value the interface variable is storing is too large, Go's
implementation has to allocate space for the value separately and put
a pointer to it in the interface variable. Since there is no way to
mutate the value in the interface, Go doesn't have to copy this
separate value each time you copy the interface, it just has to copy
the pointer. This, however, is just an optimization. If there were
some way to mutate the value in the interface, Go would have to copy
it each time you copied the interface. When you put a value into or
take it out of an interface variable, it makes a copy.

John Pritchard

unread,
Jun 8, 2011, 1:43:48 PM6/8/11
to chris dollin, golang-nuts

Chris,

Trying to avoid the debate until settling on what it is we're debating.  Frankly, not really expecting a debate, per se.

Thanks,
John

John Pritchard

unread,
Jun 8, 2011, 1:48:11 PM6/8/11
to Steven, golang-nuts

Steven,  

Your comments would reinforce my concern.  "All assignments create copies" means "assignment copies implicitly" for values without a natural implicit copy (machine words).

In assembler, for example, a move instruction is a copy.  The machine has no other semantics to offer from its electrical foundation.

In software, it's conventional to employ a machine word as an address to a location with a data structure.  The ability to control the use of that data structure is a principal concern in Go.

Thanks,

John

bflm

unread,
Jun 8, 2011, 2:27:10 PM6/8/11
to golan...@googlegroups.com, Steven
On Wednesday, June 8, 2011 7:48:11 PM UTC+2, John Pritchard wrote:
Your comments would reinforce my concern.  "All assignments create copies" means "assignment copies implicitly" for values without a natural implicit copy (machine words).

In assembler, for example, a move instruction is a copy.  The machine has no other semantics to offer from its electrical foundation.

In software, it's conventional to employ a machine word as an address to a location with a data structure.  The ability to control the use of that data structure is a principal concern in Go.

I would like to join Chris in the club: I have mostly no idea what you are talking about (in the last 2 or 3 posts of yours). Especially I want to point out the last paragraph above - I'm completely lost there.

Anyway, in Go one has (lightly simplified) the same level of control about the bits getting moved as in C. The programmer explicitly writes e.g. "p = q" to copy/move a pointer and "*p = *q" to copy/move the pointee. Also e.g. "*structPtr = myStruct", "structPtr = &myStruct" or "thatStruct = thisStruct".

HTH

Ian Lance Taylor

unread,
Jun 8, 2011, 2:32:37 PM6/8/11
to John Pritchard, golang-nuts
John Pritchard <john.dougla...@gmail.com> writes:

> There's a value of struct syntax with implicit copy on assignment? And pass
> by value is a reference to a copy? (The only way to avoid copies is via
> pointer syntax? interface syntax?)
>
> I must have misunderstood something in my off hours reading.
>
> This is the primary cause of my thinking that reference syntax and semantics
> have been truncated in an awkward way.

I think it's a lot easier to consider that everything in Go is always
passed by value, that channels, maps, and functions are pointers, and
that slices contain pointers. Of course, for that it helps that I come
from a C/C++ background.

Ian

John Pritchard

unread,
Jun 8, 2011, 2:37:00 PM6/8/11
to golan...@googlegroups.com, Steven

In 

type Foo struct {
  a int64
  b int64

var Bar = new (Foo)
var GeeWhiz = Bar

What I understand is that GeeWhiz is a copy of Bar, such that Bar != GeeWhiz

Meanwhile, back at the ranch, Bar.a == GeeWhiz.a, using a nice reference syntax.

However the reference syntax is broken at "GeeWhiz = Bar" by the copy in the assignment.


bflm

unread,
Jun 8, 2011, 2:47:42 PM6/8/11
to golan...@googlegroups.com, Steven
On Wednesday, June 8, 2011 8:37:00 PM UTC+2, John Pritchard wrote:

In 

type Foo struct {
  a int64
  b int64

var Bar = new (Foo)
var GeeWhiz = Bar

What I understand is that GeeWhiz is a copy of Bar, such that Bar != GeeWhiz

No, GeeWhiz has type *Foo by inference.
 

Meanwhile, back at the ranch, Bar.a == GeeWhiz.a, using a nice reference syntax.

Yes. You can read it also as (*Bar).a == (*GeeWhiz).a.
 
However the reference syntax is broken at "GeeWhiz = Bar" by the copy in the assignment.

The pointer (having type *Foo) is copied, not the struct. To copy the struct one would have to write e.g. "var GeeWhiz = *Bar".

John Pritchard

unread,
Jun 8, 2011, 2:48:04 PM6/8/11
to golan...@googlegroups.com

Implications include those of what I'd call implicit copies, and a confusing logic of syntax and semantics.  Both of which may be seen as risks to the longevity of this interesting new lang.

On Wed, Jun 8, 2011 at 2:37 PM, John Pritchard <john.dougla...@gmail.com> wrote:

][ the reference syntax is broken at "GeeWhiz = Bar" by the copy in the assignment.





chris dollin

unread,
Jun 8, 2011, 2:51:48 PM6/8/11
to John Pritchard, golan...@googlegroups.com, Steven
On 8 June 2011 19:37, John Pritchard <john.dougla...@gmail.com> wrote:
>
> In
> type Foo struct {
>   a int64
>   b int64
> }
> var Bar = new (Foo)

(An explicit construction of a pointer)

> var GeeWhiz = Bar

(The [pointer] value of GeeWhiz is the same as that of Bar)

> What I understand is that GeeWhiz is a copy of Bar, such that Bar != GeeWhiz

What makes you think this? It is incorrect.

> Meanwhile, back at the ranch, Bar.a == GeeWhiz.a, using a nice reference
> syntax.

The values of those expressions are the same because
they are the values of the same location.

> However the reference syntax is broken at "GeeWhiz = Bar" by the copy in the
> assignment.

How can a statement in the language break its syntax?

John Pritchard

unread,
Jun 8, 2011, 2:52:22 PM6/8/11
to golan...@googlegroups.com

That makes more sense..

On Wed, Jun 8, 2011 at 2:47 PM, bflm <befeleme...@gmail.com> wrote:
On Wednesday, June 8, 2011 8:37:00 PM UTC+2, John Pritchard wrote:
 

What I understand is that GeeWhiz is a copy of Bar, such that Bar != GeeWhiz

No, GeeWhiz has type *Foo by inference.
 
 
However the reference syntax is broken at "GeeWhiz = Bar" by the copy in the assignment.

chris dollin

unread,
Jun 8, 2011, 2:53:24 PM6/8/11
to John Pritchard, golan...@googlegroups.com
On 8 June 2011 19:48, John Pritchard <john.dougla...@gmail.com> wrote:
>
> Implications include those of what I'd call implicit copies, and a confusing
> logic of syntax and semantics.

The logic here is shared by a number of languages,
including C, which also has what you choose (for some
reason) to call "implicit copies" of struct values.

>  Both of which may be seen as risks to the
> longevity of this interesting new lang.

Maybe.

Steven

unread,
Jun 8, 2011, 2:54:26 PM6/8/11
to John Pritchard, golan...@googlegroups.com
On Wednesday, June 8, 2011, John Pritchard
<john.dougla...@gmail.com> wrote:
>
> In
> type Foo struct {  a int64  b int64
> }
> var Bar = new (Foo)var GeeWhiz = Bar

>
>
> What I understand is that GeeWhiz is a copy of Bar,

Yes. Bar is a pointer of type *Foo. GeeWhiz is a pointer whose value
is a copy of Bar's value. However, they both point to the same Foo
value, which does not get copied in the assignment.

> such that Bar != GeeWhiz

No, Bar == GeeWhiz. They are separate variables (one being a copy of
the other) so &Bar != &GeeWhiz.

> Meanwhile, back at the ranch, Bar.a == GeeWhiz.a, using a nice reference syntax.

No reference syntax. Bar.a is short for (*Bar).a. Since Bar ==
GeeWhiz, *Bar and *GeeWhiz are at the same location in memory, so
Bar.a == GeeWhiz.a by definition.

> However the reference syntax is broken at "GeeWhiz = Bar" by the copy in the assignment.

No reference syntax exists to be broken. The assignment only copies
the address. It doesn't copy the Foo that Bar points to.

bflm

unread,
Jun 8, 2011, 2:57:43 PM6/8/11
to golan...@googlegroups.com
On Wednesday, June 8, 2011 8:48:04 PM UTC+2, John Pritchard wrote:

Implications include those of what I'd call implicit copies, and a confusing logic of syntax and semantics.  Both of which may be seen as risks to the longevity of this interesting new lang.

Please explain what are you meaning by those "implicit copies".

The assignment statement always assigns, i.e. copies the RHS to LHS. I can't see anything worth naming "implicit" or "explicit" in that. The LHS and RHS must be assignment compatible as expected (i.e. usually they have the same type). It's all the same as in C. Is there some kind of "implicit copies" in C according to you?

Steven

unread,
Jun 8, 2011, 3:00:42 PM6/8/11
to John Pritchard, golan...@googlegroups.com

I strongly suggest you go here: http://golang.org/doc/play/ to
investigate and test out your assumptions about how pointers work.

John Pritchard

unread,
Jun 8, 2011, 3:06:27 PM6/8/11
to golan...@googlegroups.com


I would call a memcopy under the covers an implicity copy if it's a side effect of something like an assignment

Of course all of this points to some needs in the docs

bflm

unread,
Jun 8, 2011, 3:14:07 PM6/8/11
to golan...@googlegroups.com
On Wednesday, June 8, 2011 9:06:27 PM UTC+2, John Pritchard wrote:


I would call a memcopy under the covers an implicity copy if it's a side effect of something like an assignment

If I want to copy (using an assignment) a pointer I must write it explicitly. If I want to copy the pointee I must write it also explicitly (and in a different way). There is no implicit version selected "under the covers" by the compiler.

Russ Cox

unread,
Jun 8, 2011, 3:18:13 PM6/8/11
to John Pritchard, golang-nuts
An assignment of a value of type 'pointer to struct'
means the same thing in Go that it does in C: the
pointer is copied.

An assignment of a value of type 'struct' also
means the same thing in Go that it does in C: the
struct is copied.

In fact, unlike C, an assignment in Go *always*
means that there is a copy being made. That's
what assignment does: it copies the value on the
right hand side into the storage used for the value
on the left.

It doesn't matter whether you are copying a pointer,
a struct, an array, a function, or whatever: the data
representing that value gets copied.

It's much simpler than it is being made out to be.

Russ

Steven

unread,
Jun 8, 2011, 3:20:08 PM6/8/11
to John Pritchard, golan...@googlegroups.com
On Wednesday, June 8, 2011, John Pritchard
<john.dougla...@gmail.com> wrote:
>
>
> I would call a memcopy under the covers an implicity copy if it's a side effect of something like an assignment
> Of course all of this points to some needs in the docs

What language are you coming from where an assignment *doesn't* create
a copy? Copying *is* the effect of an assignment, not a side effect.
Even in, say, Java, an assignment creates a copy. Objects in Java are
references, so copying them does not copy their contents.

chris dollin

unread,
Jun 8, 2011, 3:40:57 PM6/8/11
to John Pritchard, golan...@googlegroups.com
On 8 June 2011 20:06, John Pritchard <john.dougla...@gmail.com> wrote:
>
> I would call a memcopy under the covers an implicity copy if it's a side
> effect of something like an assignment

Why?

The whole /point/ of an assignment is to do a copy: the
target variable's value becomes a copy of the source
expression's value.

Whether it's done by a call to a memcpy-like function,
a single machine instruction like MOV R1, #17, or a
bunch of machine instructions like TAD x; DCA y or
LDM Rs, {R4, R5, R7}; STM Rd, {R4, R5, R7} is
only an (implementationally important) detail.

> Of course all of this points to some needs in the docs

To explain what, exactly?

Chrus

--
Chris "allusive" Dollin

John Pritchard

unread,
Jun 8, 2011, 3:51:37 PM6/8/11
to r...@golang.org, golang-nuts

Would be good to develop this discussion of the type system in the docs

unread,
Jun 9, 2011, 2:10:01 AM6/9/11
to golang-nuts
On Jun 8, 5:49 pm, Ian Lance Taylor <i...@google.com> wrote:
> Miguel Pignatelli <miguel.pignate...@uv.es> writes:
> > Although it is a bit annoying sometimes, I like that go complains
> > about variables (and packages) declared and not used. It "forces" me
> > the habit to write cleaner code.
> > But why this doesn't happen in function parameters?
>
> > func test (param1 int) {
> >    return
> > }
>
> An unused variable is probably a bug.  An unused package is a dependency
> you can clean up.  An unused parameter doesn't really indicate a bug or
> a dependency issue.  If the function exists to implement an interface,
> then an unused parameter is entirely normal.

I suppose by "function exists to implement an interface" you mean any
kind of interface, not just Go interfaces per se. That is, the
programmer can take the address of the function.

In Go, it would be possible to report unused parameters if the
function is private to the package. The command "gopack" would be able
to report unused parameters of *unexported* functions whose address is
never taken. In addition, the reflect package would need to prevent
the programmer from finding the unexported function via run-time
reflection. The linker would be able to report unused parameters of
*exported* functions whose address is never taken (not even via
reflection) ... so in the end, reporting unused parameters in a
language like Go is not feasible in practice.

... but a specialized tool that goes through the source codes and
reports *potentially* unused parameters is feasible.

bflm

unread,
Jun 9, 2011, 2:50:44 AM6/9/11
to golang-nuts
On Jun 9, 8:10 am, ⚛ <0xe2.0x9a.0...@gmail.com> wrote:
> In Go, it would be possible to report unused parameters if the
> function is private to the package. The command "gopack" would be able
> to report unused parameters of *unexported* functions whose address is
> never taken. In addition, the reflect package would need to prevent
> the programmer from finding the unexported function via run-time
> reflection. The linker would be able to report unused parameters of
> *exported* functions whose address is never taken (not even via
> reflection) ... so in the end, reporting unused parameters in a
> language like Go is not feasible in practice.
>
> ... but a specialized tool that goes through the source codes and
> reports *potentially* unused parameters is feasible.

Yeah, and such valuable tool should definitely also report in detail
about the prose style used in any comments found in the sources ;-)

unread,
Jun 9, 2011, 2:56:49 AM6/9/11
to golang-nuts
Yes, it might. Why not?

Jörg Walter

unread,
Jun 9, 2011, 8:45:11 AM6/9/11
to golang-nuts

Now that's what I call a community. You're away for a single day and heaps of feedback. Thank you all!


I have updated the review, it should address all questions and incorporate all answers I have gotten.


Find it at the old place:


http://www.syntax-k.de/projekte/go-review


Two new questions have popped up, maybe someone can enlighten me?


About the garbage collector: How well does it handle large numbers of small objects?


About scheduling goroutines: Can a goroutine starve all other goroutines and the main program if it runs into an endless loop, or is there some sort of preemption as a safeguard?


--

Cheers,

Jörg

Dmitriy Vyukov

unread,
Jun 9, 2011, 8:48:48 AM6/9/11
to Jörg Walter, golang-nuts
On Thu, Jun 9, 2011 at 4:45 PM, Jörg Walter <gol...@syntax-k.de> wrote:

About scheduling goroutines: Can a goroutine starve all other goroutines and the main program if it runs into an endless loop, or is there some sort of preemption as a safeguard?



At least for programs compiled with 6g/8g a goroutine can starve other goroutines and garbage collection. That is, all goroutines have to periodically pass via special points (I guess it's memory allocation, syscalls, Printf, Gosched, etc).

roger peppe

unread,
Jun 9, 2011, 8:56:31 AM6/9/11
to Jörg Walter, golang-nuts
On 9 June 2011 13:45, Jörg Walter <gol...@syntax-k.de> wrote:
> About scheduling goroutines: Can a goroutine starve all other goroutines and
> the main program if it runs into an endless loop, or is there some sort of
> preemption as a safeguard?

there is no guarantee. currently with GOMAXPROCS=1
(the default) there is no preemption, and a looping goroutine can starve
all other goroutines.

Jörg Walter

unread,
Jun 9, 2011, 9:43:46 AM6/9/11
to golang-nuts

I feared this would be the case. Is there something fundamentally different with GOMAXPROCS > 1 or do two looping goroutines starve a GOMAXPROCS=2 program?


--

Cheers,

Jörg

Dmitriy Vyukov

unread,
Jun 9, 2011, 9:52:50 AM6/9/11
to Jörg Walter, golang-nuts
I suspect 1 looping goroutine hangs whole program regardless of  GOMAXPROCS value. It happens during GC request (during "stop the world").

bflm

unread,
Jun 9, 2011, 9:59:33 AM6/9/11
to golang-nuts
On Jun 9, 3:43 pm, Jörg Walter <gol...@syntax-k.de> wrote:
> I feared this would be the case. Is there something fundamentally
> different with GOMAXPROCS > 1 or do two looping goroutines starve a
> GOMAXPROCS=2 program?

Why feared? Two goroutines, where one of them never gives up and the
other one waits for the first to finish (or yield some comm event), is
exactly the same situation with two threads doing the same as above in
any other language. The resulting behavior is no surprise in both
cases.

andrey mirtchovski

unread,
Jun 9, 2011, 10:11:32 AM6/9/11
to Dmitriy Vyukov, Jörg Walter, golang-nuts
> I suspect 1 looping goroutine hangs whole program regardless of  GOMAXPROCS
> value. It happens during GC request (during "stop the world").

$ cat t.go
package main

import "fmt"

func main() {
c := make(chan bool, 0)
go func() {
for {
}
c <- true
}()

for {
select {
case <-c:
fmt.Println("shouldn't happen")
default:
fmt.Println("bumblebee")
}
}
}
$ 6g t.go; 6l t.6
$ export GOMAXPROCS=1
$ ./6.out
bumblebee
^C
$ export GOMAXPROCS=2
$ ./6.out | head
bumblebee
bumblebee
bumblebee
bumblebee
bumblebee
bumblebee
bumblebee
bumblebee
bumblebee
bumblebee
^C

Dmitriy Vyukov

unread,
Jun 9, 2011, 10:11:58 AM6/9/11
to bflm, golang-nuts
The problem with Go is that it introduces implicit dependencies between goroutines via GC. So in your program there is no dependencies, but every memory allocation can implicitly wait for any other goroutine to yield.

Not saying that goroutines are formally cooperative, which is not a case with OS threads that are preemptive.

Russ Cox

unread,
Jun 9, 2011, 10:17:45 AM6/9/11
to Dmitriy Vyukov, bflm, golang-nuts
> The problem with Go is that it introduces implicit dependencies between
> goroutines via GC. So in your program there is no dependencies, but every
> memory allocation can implicitly wait for any other goroutine to yield.
> Not saying that goroutines are formally cooperative, which is not a case
> with OS threads that are preemptive.

This is a problem with the current Go implementations.
It is not a problem with Go the language.

Russ

Dmitriy Vyukov

unread,
Jun 9, 2011, 10:18:13 AM6/9/11
to andrey mirtchovski, Jörg Walter, golang-nuts
package main
import "fmt"
import "runtime"
func main() {
compl := make(chan int)
go func() {
for {
}
compl <- 0
}()
       for {
               select {
               case <-compl:
                       fmt.Println("shouldn't happen")
               default:
                       fmt.Println("bumblebee")
runtime.GC()
               }
       }
}


$ ./test
bumblebee
^C


andrey mirtchovski

unread,
Jun 9, 2011, 10:22:32 AM6/9/11
to Dmitriy Vyukov, Jörg Walter, golang-nuts
> runtime.GC()

aha!

Ian Lance Taylor

unread,
Jun 9, 2011, 10:34:43 AM6/9/11
to Jörg Walter, golang-nuts
Jörg Walter <gol...@syntax-k.de> writes:

> About the garbage collector: How well does it handle large numbers of
> small objects?

There is a small amount of per-object overhead in the garbage collector.
There is no particular other problem with large numbers of objects, big
or small. If you want to slow down the current garbage collector, the
best way is to have a bunch of medium sized arrays and only keep
pointers to elements toward the end, with no pointers to the start of
the arrays. That won't give you a major slowdown, but it will increase
the constant factors of dealing with each object, which I would expect
to be measurable although I haven't tried.


> About scheduling goroutines: Can a goroutine starve all other goroutines
> and the main program if it runs into an endless loop, or is there some
> sort of preemption as a safeguard?

As others have said, there is no preemption at present when using 6g/8g.

These are good points to note at present but of course we are continuing
to work on the garbage collector and the scheduler. They are not part
of the language definition.

Ian

Ian Lance Taylor

unread,
Jun 9, 2011, 10:59:14 AM6/9/11
to r...@golang.org, Dmitriy Vyukov, bflm, golang-nuts
Russ Cox <r...@golang.org> writes:

In particular, while the gccgo implementation of goroutines has many
deficiencies, it does not suffer from this particular problem.

Ian

unread,
Jun 9, 2011, 2:07:17 PM6/9/11
to golang-nuts
On Jun 9, 2:45 pm, Jörg Walter <gol...@syntax-k.de> wrote:
> About the garbage collector: How well does it handle large numbers of
> small objects?

You may be interested to take a look at this pathological case:
http://groups.google.com/group/golang-nuts/msg/3bc233719afe7ff8

Searching the golang-nuts mailing list for garbage-collection related
topics will reveal some more discussions about the GC.

In your review, you wrote that "A decent garbage collector can
actually be faster than manual memory management by postponing
bookkeeping until there is time and completely avoiding bookkeeping by
reusing unused objects". In my opinion, this isn't true. Moreover, the
term "postpone bookkeeping until there is time" is non-sense (well, at
least to me). There is no way for *any* garbage collector to be
faster than *highly-optimized* C code compiled with an optimizing
compiler (GCC, ICC, CLang or whatever compiler) - it may sound
unbelievable, but it is the truth.

One advantage of the Go runtime (in comparison to Java for example) is
that you can manually deallocate memory, if you are absolutely sure
that it isn't used anymore. Look at the function
"runtime.Free(*byte)". Well, a problem is that Go (as far as I know)
currently has no standard&fast way of getting to the pointers used by
built-in Go data types (most notably: the map type).

Dmitriy Vyukov

unread,
Jun 9, 2011, 2:12:54 PM6/9/11
to ⚛, golang-nuts
On Thu, Jun 9, 2011 at 10:07 PM, ⚛ <0xe2.0x...@gmail.com> wrote:
In your review, you wrote that "A decent garbage collector can
actually be faster than manual memory management by postponing
bookkeeping until there is time and completely avoiding bookkeeping by
reusing unused objects". In my opinion, this isn't true. Moreover, the
term "postpone bookkeeping until there is time" is non-sense (well, at
least to me).   There is no way for *any* garbage collector to be
faster than *highly-optimized* C code compiled with an optimizing
compiler (GCC, ICC, CLang or whatever compiler) - it may sound
unbelievable, but it is the truth.


In concurrent application it's frequently required to use reference-counting for manual object life-time management. And in this situation GC (mark and sweep for example) can easily be faster because GC time complexity depends only on number of live objects at GC time, while reference counting time complexity depends on number of operations on references. That can be 10 vs 1000000000.

Jörg Walter

unread,
Jun 9, 2011, 6:11:23 PM6/9/11
to golang-nuts

On Dunnersdag, de 9. Juni 2011, Ian Lance Taylor wrote:

> These are good points to note at present but of course we are

> continuing to work on the garbage collector and the scheduler. They

> are not part of the language definition.


I am totally aware of the fact that other things are more important. I just wanted to know (and document ^^) them. I agree with your implication, the language definition has highest priority, it must be right. Everything else is implementations and library.


You may be interested in the discussion my article has evoked in several places, like:


http://news.ycombinator.com/item?id=2631964


http://www.reddit.com/r/programming/comments/hudvd/the_go_programming_language_or_why_all_clike/


http://lwn.net/Articles/446598/



I've updated the feedback section to also address them. It's good to see some more controversial discussion, it gives you an outside perspective on things. In here there's more of a fan group :)



On Dunnersdag, de 9. Juni 2011, ⚛ <0xe2.0x...@gmail.com> wrote:

> In my opinion, this isn't true. Moreover, the

> term "postpone bookkeeping until there is time" is non-sense (well, at

> least to me). There is no way for *any* garbage collector to be

> faster than *highly-optimized* C code compiled with an optimizing

> compiler (GCC, ICC, CLang or whatever compiler) - it may sound

> unbelievable, but it is the truth.


Postpone meaning, if you're in a tight, time-critical loop that constantly allocates and deallocates a few objects, it's way faster to reuse those deallocated-but-not-freed objects and have a full GC run later when that loop is over and CPU time is left (typical UI workload!). The free list approach is used by GCs as well as by reference counters to great success, but in traditional C you'd have to do manually what these do automatically.


There was a truly great paper by Dan Sugalski (of Perl6 fame) explaining the (back then, like many years ago) up and coming Perl6 GC in much detail, covering many different approaches to GC and how they evolved. A very inspiring read. I tried to find it for my article already, but alas, Google failed me. Should you find it, read it and send me a link.


Also, what Dmitriy said.


--

Cheers,

Jörg

unread,
Jun 10, 2011, 4:06:31 AM6/10/11
to golang-nuts
On Jun 10, 12:11 am, Jörg Walter <gol...@syntax-k.de> wrote:
> On Dunnersdag, de 9. Juni 2011, ⚛ <0xe2.0x9a.0...@gmail.com> wrote:
>
> > In my opinion, this isn't true. Moreover, the
> > term "postpone bookkeeping until there is time" is non-sense (well, at
> > least to me).   There is no way for *any* garbage collector to be
> > faster than *highly-optimized* C code compiled with an optimizing
> > compiler (GCC, ICC, CLang or whatever compiler) - it may sound
> > unbelievable, but it is the truth.
>
> Postpone meaning, if you're in a tight, time-critical loop that constantly
> allocates and deallocates a few objects, it's way faster to reuse those
> deallocated-but-not-freed objects and have a full GC run later when that
> loop is over and CPU time is left (typical UI workload!).

Yes, I agree. But skilled C/C++ programmers who care about performance
are routinely doing what you just described without even thinking
about it. The human brain is quite capable of quickly computing what
particular memory allocation scheme (CPU register, stack, malloc,
realloc, pool, object reuse) to use in a given situation. Some of
the obvious drawbacks are: programmers make programming errors,
writing (and maintaining) more lines of code takes more time than
writing less lines of code, there are more degrees of freedom that the
programmer has to deal with, the programmer has to know about the
available allocation strategies and has to be able to estimate their
performance implications.

> The free list
> approach is used by GCs as well as by reference counters to great success,
> but in traditional C you'd have to do manually what these do
> automatically.

I know what you mean. A problem I see here is that you might be
overestimating the capabilities of GC algorithms. They are just
algorithms, so they are *constrained in their capabilities*, they
don't have knowledge about the problem space. A skilled programmer
will in most cases beat any GC in existence (even if he/she has to
invent a new or improve an existing memory management strategy along
the way).

Ok, a small example might better reveal what I mean: Imagine you have
a GUI application written in Java. You are using the class "Point" in
the code, which has two fields "x" and "y" of type "int". Each
instance of the class "Point" has to be allocated via "new
Point(x,y)". Out of these allocations, only a small percentage (if any
at all) actually needs to be allocated on the heap or from a pool -
for the most part, instances of "Point" are so simple that it would be
sufficient to allocate them in registers or in the stack frame of the
function. The crucial question is: Is Java's GC capable of determining
which instances of "Point" do *not* need to be allocated from the heap
nor from any pool? Are *you* able to answer this question? Compare
to what a C/C++ programmer would do: "Point" is a structure normally
passed by value. Therefore, the C/C++ programmer will beat Java's GC
algorithm without even thinking about it! It may sound unbelievable,
but it is the truth. In addition, another crucial factor in Java
code is not the capabilities of the GC algorithm, but the fact that
the Java *programmer* does not know (and does not even care!) whether
Java's GC algorithm will be able to determine which instances of
"Point" can be allocated in registers of the CPU or in the stack frame
of the function.

Marko Mikulicic

unread,
Jun 10, 2011, 5:45:35 AM6/10/11
to ⚛, golang-nuts
On 10 June 2011 10:06, ⚛ <0xe2.0x...@gmail.com> wrote:

> The free list
> approach is used by GCs as well as by reference counters to great success,
> but in traditional C you'd have to do manually what these do
> automatically.

I know what you mean. A problem I see here is that you might be
overestimating the capabilities of GC algorithms. They are just
algorithms, so they are *constrained in their capabilities*, they
don't have knowledge about the problem space. A skilled programmer
will in most cases beat any GC in existence (even if he/she has to
invent a new or improve an existing memory management strategy along
the way).

"any skilled assembler programmer can certainly do better than a compiler algorithms, which are 
*constrained in it's capability*, they don't have knowledge about the problem space. A skilled programmer
will in most cases beat any compiler in existence (even if he/she has to invent..."
 
This sometimes holds true, but sometimes not. 

A famous example is http://goo.gl/QAxSi, but I'm sure there are plenty of them. I don't want to put down the power of human's creativity,
but let's face it, we are not always breakthrough creative and able to invent new ways to do things; probably only a few times, so let's invest it where it's worth.


Ok, a small example might better reveal what I mean: Imagine you have
a GUI application written in Java. You are using the class "Point" in
the code, which has two fields "x" and "y" of type "int". Each
instance of the class "Point" has to be allocated via "new
Point(x,y)". Out of these allocations, only a small percentage (if any
at all) actually needs to be allocated on the heap or from a pool -
for the most part, instances of "Point" are so simple that it would be
sufficient to allocate them in registers or in the stack frame of the
function. The crucial question is: Is Java's GC capable of determining
which instances of "Point" do *not* need to be allocated from the heap
nor from any pool? Are *you* able to answer this question?     Compare
to what a C/C++ programmer would do: "Point" is a structure normally
passed by value.

As long as the reference is not stored outside of the scope, the compiler *could* do this kind of optimization, it doesn't 
have anything to do with to GC or not to GC, it's just a compiler optimization. The GC is needed when you have stuff allocated on heaps which can be shared,
it's used to track pointers. If the compiler knows that it can be allocated safely on the stack, the GC is not yet affected, at least until the object has to be "promoted" as a shareable object, perhaps in
an unlikely case.

The interesting point is that most of the times all this is not necessary. The advantage of putting stuff on the stack is that deallocation is automatic, and the speed of deallocation actually doesn't 
depend on how many tiny or big objects you 'allocated' on the stack. The same happens in the young generation of copy compacting garbage collectors, the complexity of the deallocation
depends on the number of surviving objects (i.e. reachable).  If the given problem requires a number of objects to survive and become reachable from outside, even the manual approach will do a copy on the heap of
the survivors. Also take into consideration that the "allocation" of an object in a copy-compacting gc is nothing more than a addition/subtraction, like creating a stack frame.

I'm sure there are better examples of allocation strategies which might benefit from knowing something more intimate about the problems space, like context-specific pools which can be handled
with different policies or freed in block when something application-specific happens.
I have the impression that if this were a crucial performance aspect, GC designers will accommodate the possibility to manage different heaps, etc.
I don't know why commercial solutions don't employ that, it could be because they don't care about this niche, or because they effectively measured it's not a mayor benefit.


Of course you can always argue that the whole system is too big and does too much things, and that it would be better if environments remain understandable by a human being (like go), but this
is a different point; what I was trying to point out is that there is no problem *in principle* with the GC itself.

But, of course manual control is very nice thing in some situations, and I'm pretty sure that most people are trying to find a productivity balance, trying to avoid premature optimization
which is not only a cost of development (fun) but also maintenance, debugging etc. but if an environment allows for effective manual optimization of the hot spots you
can have the benefits of both world. Unfortunately not all bridges are toll-less.
 
Therefore, the C/C++ programmer will beat Java's GC
algorithm without even thinking about it! It may sound unbelievable,
but it is the truth.  

you forgot to highlight "skilled programmer" :-) Well, I'm not so optimistic like you, I'm sure that a skilled human can produce better code if needed, but I also feel that
in most cases it's not "without even thinking", current state of the art GC and JIT are marvelous beasts, usually the whole thing is crippled because of a lot of issues with come along
the whole stack.

Of course, try to complicate the picture and introduce a highly concurrent application and it would be interesting to see how this skilled c/c++ developer
can do better than today's state of the art GC (not talking about java in particular, keep also in mind that there are a number of GC and JIT implementations for the JVM)

 
  In addition, another crucial factor in Java
code is not the capabilities of the GC algorithm, but the fact that
the Java *programmer* does not know (and does not even care!) whether
Java's GC algorithm will be able to determine which instances of
"Point" can be allocated in registers of the CPU or in the stack frame
of the function.

You might be interested in this talk: http://www.youtube.com/watch?v=uL2D3qzHtqY

Anyway, there is a fundamental truth in what  you say, most java programmers probably think that there is some more magic
than it really is.

Cheers,
Marko

Reply all
Reply to author
Forward
0 new messages