Am I in the minority to think of Go as a completely unnecessary move-along-now-nothing-to-see-here project? (as if we didn't have enough of that already). The only niche I see for it is for those poor souls who are still wasting their time with Python/Ruby but that by itself surely can't lead to great things for the language, especially since it's riding on air. More dense air than Python but air nonetheless. Also Ro…
> Am I in the minority to think of Go as a completely unnecessary move-along-now-nothing-to-see-here project? Ignoring your broadside of insults, I keep asking myself the same thing after working with it: What is so compelling about Go? It's better than C, but we already have good choices in that area. I feel like there's a bandwagon effect around the language.
The State of Go: Where we are in February 2016
91–100 of 224 posts
Re: The State of Go: Where we are in February 2016
#92Earlier quoted context omitted.
At the x86 level, myPool.Get(Index) is going to be at least as expensive as cmp/jae/mov (3 cycles), and myPool.Get().(myStruct) is going to be at least as expensive as cmp/jae/cmp/jne/mov (5 cycles). So unless you have some way of hiding the latency, the type check is 67% slower by cycle count. The experience of every JIT developer is that dynamic type checks do matter a lot in hot paths.
This is a small fixed cost as compared to the cost of not using the pool. I wasn't suggesting the operation is free.
Re: The State of Go: Where we are in February 2016
#93The Go runtime is really starting to look sexy. 20 ms GC pauses on 200+ GB heaps! I remember a thread discussing a pauseless GC on the dev mailing-list; where Gil Tene, of Azul C4's fame, commented on having a clear policy on safepoints from the beginning was paramount to having a good GC. It looked like the community is very biased towards doing the fundamental things well, and attracting the right people. And on to…
The only thing missing is a good binding to a javascript engine, for code that has to run on both client and server.
Re: The State of Go: Where we are in February 2016
#94Earlier quoted context omitted.
Although Go's GC is tunable to some extent, the open source HotSpot JVM are already has multiple GC implementations that you can choose based on your use case and further tune. There is also work being done in the OpenJDK project for a GC that can collect > 100GB heaps in [1] http://openjdk.java.net/jeps/189 [2] https://www.azul.com/products/zing/
From this "work being done in the OpenJDK project for a GC that can collect > 100GB heaps in https://talks.golang.org/2016/state-of-go.slide#37 https://github.com/golang/proposal/blob/master/design/12800-...
In particular, Go's GC is not yet generational from the talks I've seen, which is a large throughput loss compared to the GC of the JVM.
Re: The State of Go: Where we are in February 2016
#95At work (Lytics) 100% of our backend code has been in Go since the beginning over 3 years ago, so slide #6 highlights one of the most things with nearly every Go release: > Changes to the language: None https://talks.golang.org/2016/state-of-go.slide#6 We generally get our entire stack upgraded to the latest release within 1-3 months with little effort. It wouldn't be much more work to be ready to upgrade on release…
Considering the nature of the work, the programming field seems to be particularly rife with "common wisdom" that's not supported by data. This especially goes towards language design. (In the Chris Granger talk that was recently posted here, he noted that programmers who said they "never" used the mouse, only the keyboard, actually used the mouse 50% of the time.)
The reality of the programming field is that it's "almost a field" [1] -- struggling just as much with empiricism as alchemy was before it evolved into the science of chemistry. Language features definitely suffer from the irrationality of the almost-a-field of programming.
Golang seems to be led by good empiricists who are targeting a specific set of use cases for programming in the large.
[1] - https://news.ycombinator.com/item?id=9812487Re: The State of Go: Where we are in February 2016
#96Earlier quoted context omitted.
Have you benched "myPool.Get()" vs "myPool.Get().(*myStruct)" ? I don't think the "type manipulation" is the problem you think it is.
At the x86 level, myPool.Get(Index) is going to be at least as expensive as cmp/jae/mov (3 cycles), and myPool.Get().(myStruct) is going to be at least as expensive as cmp/jae/cmp/jne/mov (5 cycles). So unless you have some way of hiding the latency, the type check is 67% slower by cycle count. The experience of every JIT developer is that dynamic type checks do matter a lot in hot paths.
If that branch is mispredicted, we're talking about 12-20 cycles. Ok, I assume it's a range check and thus (nearly) always not taken. So if it's in hot path, it'll always be correctly predicted. Modern CPUs will most likely fuse cmp+jae into one micro-op, so predicted-not-taken + mov will take 2 cycles (+latency).
"cmp/jae/cmp/jne/mov" will of course be fused into 3 micro-ops. But don't you mean "cmp/jae/cmp/je/mov"? I'm assuming second compare is a NULL check (or at least that instructions are ordered that way second branch is practically never taken). I think that also takes 2 cycles (both branches execute on same clock cycle + mov), but not sure how fused predicted-not-takens behave.
L3 miss for that mov, well... might well be 200 cycles.
Re: The State of Go: Where we are in February 2016
#97Earlier quoted context omitted.
This is a small fixed cost as compared to the cost of not using the pool. I wasn't suggesting the operation is free.
But not using a pool is not the alternative we are talking about. Rather its hand rolling your own every time. Something the JVM doesn't require.
So your had rolled one will not have the typing overhead we are discussing, but it will have 2 much worse issues.
1. sync.Pool's have thread local storage, something your own pools will not have.
2. sync.Pool's are GC aware; meaning if the allocator is having trouble it can drain "free" pool objects to gain memory. Your custom pool will not have this integration.
I have a feeling that the performance you gained not type-checking you will loose by not having #1.Re: The State of Go: Where we are in February 2016
#98Earlier quoted context omitted.
At the x86 level, myPool.Get(Index) is going to be at least as expensive as cmp/jae/mov (3 cycles), and myPool.Get().(myStruct) is going to be at least as expensive as cmp/jae/cmp/jne/mov (5 cycles). So unless you have some way of hiding the latency, the type check is 67% slower by cycle count. The experience of every JIT developer is that dynamic type checks do matter a lot in hot paths.
Not disagreeing, but I think that was a bit inaccurate. If that branch is mispredicted, we're talking about 12-20 cycles. Ok, I assume it's a range check and thus (nearly) always not taken. So if it's in hot path, it'll always be correctly predicted. Modern CPUs will most likely fuse cmp+jae into one micro-op, so predicted-not-taken + mov will take 2 cycles (+latency). "cmp/jae/cmp/jne/mov" will of course be fused in…
The first compare is a bounds check against the array backing the pool, and the second compare is against the type field on the interface, not a null check. Golang interfaces are "fat pointers" with two words: a data pointer and a vtable pointer. So the first cmp is against a register, while the second cmp is against memory, data dependent on the register index. The address of the cmp has to be at least checked to determine if it faults, so I would think at least some part of it would have to be serialized after the first branch, making it slower than the version without the type guard.
Re: The State of Go: Where we are in February 2016
#99Earlier quoted context omitted.
I'd like to see evidence for this. the JVM has been great at stack allocation for over a decade [1][2]. [1] http://www.stefankrause.net/wp/?p=64 [2] http://www.ibm.com/developerworks/library/j-jtp09275/
It is straightforward because Go has first class value types which are most likely to be on stack vs Java where everything except primitives are reference type which are most likely to be on heap. Also Java data structures are really bloated. https://www.cs.virginia.edu/kim/publicity/pldi09tutorials/me...
Also that they went VM instead of AOT like those languages main implementations.
Oh well, at least they are now on the roadmap for Java 10, 30 years later.
Re: The State of Go: Where we are in February 2016
#100Earlier quoted context omitted.
Not disagreeing, but I think that was a bit inaccurate. If that branch is mispredicted, we're talking about 12-20 cycles. Ok, I assume it's a range check and thus (nearly) always not taken. So if it's in hot path, it'll always be correctly predicted. Modern CPUs will most likely fuse cmp+jae into one micro-op, so predicted-not-taken + mov will take 2 cycles (+latency). "cmp/jae/cmp/jne/mov" will of course be fused in…
Ah yeah, I wasn't sure if fusion was going to happen. You're probably right in macro-op terms; sorry about that. The first compare is a bounds check against the array backing the pool, and the second compare is against the type field on the interface, not a null check. Golang interfaces are "fat pointers" with two words: a data pointer and a vtable pointer. So the first cmp is against a register, while the second cmp…
Well, I didn't profile that case. Who knows what will really happen. Modern x86 processors are hard to understand.
> ... while the second cmp is against memory, data dependent on the register index
Hmm... that sounds like something that would dominate the cost? Memory access and data dependency. Ouch.
Also of course in that case, second compare+branch can't be fused, because cmp has a memory operand.