Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You jest?

Go is GC'd just like JVM. The only possible benefit -- even if Go catches up at runtime -- is the compact form of memory objects in Go vs Java object. But then again, if you are writing such systems (in either language) you are very likely to spend quite a lot of time in 'unsafe' land.



> if you are writing such systems (in either language) you are very likely to spend quite a lot of time in 'unsafe' land.

I don't think that's necessarily true. Go does a much better job than Java at letting you manage your allocations and re-use memory. You can write tight, performance-critical code in Go without resorting to 'unsafe'; it just requires care, as it does in any language.


I don't know if I completely agree with this. To write truly performance-critical Go, you end up throwing away many of the language's qualities. Channels are slow, defers add overhead, interfaces add overhead (e.g. I2T), etc.

Don't get me wrong, I like Go, but in my (and others I work with) experience, it's not the right choice for performance-critical systems.


I mean, Go is (or was) in the loop whenever YouTube hit its MySQL clusters (vitess) and on on the server providing downloads of Chrome and so forth (dl.google.com). CloudFlare has it sitting in the middle of every request for some sites (in the form of Railgun, their delta compression for pages). I'm not exactly a perf ninja and got some Go code packing Wikipedia history dumps at >100 MB/s. Dropbox uses Go for, their words, "our performance-critical backends" (https://blogs.dropbox.com/tech/2014/07/open-sourcing-our-go-...). So folks manage to heavy lifting with it.

I see "I couldn't possibly use X for performance reasons" here a lot, as an almost immediate response about a wide range of different tools, and two things come up in my mind: 1) you can always set the standard arbitrarily high. If you're doing AAA shoot-'em-up games or something, yes, use something else. 2) you're often not as good at tools that're new or different. It's possible you could go further with just a few more tricks about profiling or using free pools or whatever, or a little more info about how your code executes or what the runtime does. FWIW, if you hit a specific wall that's a problem for your app, folks on golang-nuts (or StackOverflow, where I've hung out sometimes) are often happy to try and help.

Hope this is more helpful than fussy. Mostly just don't want folks to be discouraged into thinking certain things are impossible when in some cases they're really being done in production out there.


No one doubts that Go is production ready at this point. But the performance requirements of a systems programming language are just very different from the requirements for a web server or applications language.

From my point of view, and the industry I'm in, the latency requirements of a web server stack look completely laughable. That's not to say there aren't challenges in a web stack, because many web servers have to handle orders of magnitude more I/O than we do, and efficient load balancing over a distributed system is extremely difficult and I am fortunate to rarely have to think about that kind of thing. But a requirement like "99% of requests need to have a response time of 200ms or lower" looks like fiddlesticks compared to a requirement like "a round-trip-time of more than 100us will be a large problem and get noticed".

My point is that Google's, CloudFlare's, and Dropbox's "performance-critical backends" don't require the same things as some other workloads. As a more mundane example, the latency requirements of Google's search engine are probably less stringent than the latency requirements of your text editor.

None of this should be taken to mean Go is slow or can't handle 99% of the world's performance requirements. But you can't just say "Go is high performance and fits in all of these company's critical paths. Try harder and it will work." Sometimes it might just not be cut out for it.


>I mean, Go is (or was) in the loop whenever YouTube hit its MySQL clusters (vitess) and on on the server providing downloads of Chrome and so forth (dl.google.com).

Not as impressive as it sounds. Most of it is cached in memory anyway...


Agreed with setting the standard arbitrarily high. It depends on what problem you're trying to solve—just like deciding when to use any other tool. Context matters.

Where I work, we've been trying to build some super-fast systems and things like the GC and even calling interface methods matter. We open sourced some data structures that show just how optimized we're trying to get (https://github.com/Workiva/go-datastructures), but in hindsight, Go might not have been the right tool for the problem.


JVM is in use in a lot more performance critical paths than Go. Go just seems new so it is easy to list the 2-3 places that use at scale.


The JVM is awesome for long running programs with minimal memory constraints. For transient programs, not so much.


I disagree with "channels are slow". They may be faster than you think. Defers needn't add as much overhead as they do today; this can be fixed.

I think it really depends on your definition of "performance-critical". I agree Go isn't suitable for all performance-critical tasks, but it covers a vast swathe of them quite comfortably.


> this can be fixed.

I believe this and am counting on it. Go2.0 and beyond should be a solid choice.

You should also note that it is entirely understood that more mature tech e.g. JVM have had the benefit of multibillion Dollar investment by SUN, IBM, Oracle, etc.

I feel it is regrettable that (imo valid and reasonable) criticism of what is currently not up to par with this tech always seemingly requires a disclaimer that "I love Go". I have been using this language since the day it was released. I know it fairly well. I like it. But excessive hype and sensitivity around it is frankly somewhat irritating.

peace out and happy v. day Go <3


Valentines day was yesterday for me. You wouldn't see me spending my time responding here if it were today!


Not an uncommon view: https://twitter.com/kellabyte/status/564531804837654528

(That's not me, to be clear.)

We all like Go. Just wish we could discuss these matters without unduly raising temperatures. "It's just code".


Sommers is an absolute beast, does totally astounding work and is an asset to the community. But even when we say "performance-critical" most of us don't mean getting 3M req/sec from one box like she did w/Haywire (https://twitter.com/kellabyte/status/547063455048404992). In other words, pushing the hardware absolutely to its limits is another game (Sommers' game :) ) from simply getting a tricky part of your app performing at the level you need. And, confusingly, "high-performance" or "performance-critical" are terms you might use to describe either task.

For context, the person whose presentation triggered Kelly's comment, MIT scholar Neha Narula, was experimenting with an 80 core machine, and she replied "it's kind of amazing I could push Go that far," and "to be fair they weren't really optimizing for my use case :)" -- her whole presentation is on YouTube at https://www.youtube.com/watch?v=Mbg1COjhsJU (some wild stuff--she got improvements for >48-core machines pushed into the Go GC) and those replies I quoted are at https://twitter.com/neha/status/564569903219634176 .


But even when we say "performance-critical" most of us don't mean getting 3M req/sec from one box like she did w/Haywire

We are not all writing web apps. Some of use are in machine learning, NLP, signal processing, etc. where squeezing out as much performance as possible does matter.

In those fields Go is still weak. No autovectorization, no OpenMP, no direct CUDA integration, GC overhead, etc. Luckily, this can often be worked around since cgo is so good. One can write performance-intensive parts in C or C++, compile with the latest gcc or clang and link it with the Go code to drive it. This is often an understated advantage of Go compared to Java, where JNI calls are expensive. But the Go camp always advocate for porting everything to Go (because fast compile times).


Indeed, we agree that Go is suitable for some things people call high-performance but not others. I do not advocate porting everything to Go. Not only is it not always a good fit, but there's a very high bar to clear to justify revamping any perfectly good codebase. (I use Python at work and wouldn't advocate for porting anything.)


What does OpenMP do for you that Go's built-in concurrency doesn't?


OpenMP is for parallelisation, not concurrency. OpenMP is designed for embarrassingly parallel loops that you typically encounter in numeric code, where parallelization is as simple as tagging a for loop with a pragma and (if necessary) marking variables that should be synchronized and/or critical sections.

E.g. you can make the libsvm library parellalized and scale up to many cores by adding two pragma statements.

I have a Go package that attempts to bring some of this functionality to Go [1]. But it's definitely not the same as having OpenMP.

[1] http://godoc.org/github.com/danieldk/par


If you read her tweets she states C++ would have been a better option, though.


I don't believe that this is true. You use the exact same patterns and tricks in both for perf-critical code: off-GC primitives and object pools rule the day. What are you considering a "much better" option available in Go?

(I considered stack-allocated structs in Go, but honestly that doesn't strike me as a particularly major thing; it may be slightly more terse, but fundamentally the same behavior.)


Go gives you data structures with fewer pointers than Java, which helps cut down on GC pressure.

    type point struct {
        x int16
        y int16
    }
    points := make([]point, 1e6)
The value points uses 4 MB of memory and contains one pointer, not a million.


Sure. Now do this in Java (I have no idea why I'm getting downvoted for this thread because I think this stuff is fairly straightforward and nobody's actually making an argument to the contrary, but whatever):

  short[] x = new short[1000000];
  short[] y = new short[1000000];
4MB of shorts. Now you can use the argument of locality of reference, to be sure--but you're already throwing out the window by keeping around a million items.

This is why I'm saying that in the what I would call most perf-critical cases, value type structs are a convenience much more than a tool to realize significant benefits. They are nice-to-haves. They don't make your code magicfast.


Values ("off-GC primitives?") are first class-citizens in Go. Stack-allocated structs have much more value than you think.


More value than I think? I'm pretty sure that I know exactly their value. I'll maintain that stack-allocated structs are a nice-to-have on top of the sort of stack-allocated primitives that Java provides; I'd like to have those structs as a convenience when I write Java, which is why I alluded to terseness in my prior post. But there's very little (or should be, I suppose, depending on implementation) performance difference to speak of between a struct and parallel declaration of the same values.


You said:

> I considered stack-allocated structs in Go, but honestly that doesn't strike me as a particularly major thing;

But for me they're one of the major ways in which I control memory use in Go programs. So, yeah, I think you underestimate them. No condescension implied. Apologies if it came across that way.

I think we probably agree more than we disagree.


Yeah, I edited it out because after I took a breath I figured you didn't mean it that way. =) Hugs all around.

But I really don't think it's a major thing, because there's no meaningful difference, in terms of performance, between "struct { int x; int y; } A" and "int Ax; int Ay;". I'm suspicious of claims that Go, as fundamentally a not that different language to a JVM language, is going to yield significant performance benefits. I'm not saying they aren't a nice convenience (value types are one of the things I love about C# when I'm writing code under MonoGame), I'm saying that I can't think of a reasonable way, barring bugs or short-sighted implementations, that they made for faster code.


If it is not a major thing JVM architects would not deliberating on this issue in such details. http://cr.openjdk.java.net/~jrose/values/values-0.html

Java value types are going to be in Java 10 i.e. years away. So may be it is not big deal for you but JVM developers think it is going to be big deal for lot of performance sensitive code.

This is despite the fact that most advanced GC available in Java.

See overhead for Java data structures.

https://www.cs.virginia.edu/kim/publicity/pldi09tutorials/me...

Go does not have this heavy overhead.


Are you aware that Java already has value types? Do you realize that the JVM has primitive collections, which completely ignore all of the boxed types that are, yes, a performance suck, via Trove? Nobody writing perf-conscious Java is using bleeping HashMap<K, V> or even ArrayList<T>. They're using Trove's TIntIntMap, TLongSet, etc. and getting the. exact. same. thing you're saying they're not.

Or they're using arrays. And here's the one difference that I have acknowledged since my first post, but there's a but to it: there is one material performance-relevant difference between parallel arrays-of-members and arrays-of-structs, and that's locality of reference. But any multithreaded (or cooperative, for that matter) system of nontrivial size is already chucking cache coherency out the window to the point where I'm very, very skeptical of the claims of magicfastness because two int members are next to one another. If you can prove that cache coherency is killing you and you need to run more consistently to avoid eviction, then you can push the problem into a minimal process without much going on and `nice` it to keep your cache lines for longer, but you're still in the land of Things That Are Not Made Easier In Go, Either.

Those JVM architects are considering structs--using the CLR term for "stack allocated aggregate types" because they're already there and I've done this side-by-side comparison in that environment, which is as close a one to the JVM as exists that supports them--as a convenience and, in rare cases and in extremity, a legitimate performance improvement. A good idea to have. But it's such a corner case that even they feel comfortable pushing it, and its ramifications, to Java 10. (If you want to see why it's a corner case: again, go look at the CLR and how rarely structs are used. I'm almost as comfortable on the CLR as the JVM, and I make video games. I use structs. I've never, ever seen them in the wild in somebody else's non-library code, where you can encapsulate your perf grossness anyway.)

Go still has the heaviest performance overhead of all: having a garbage collector in the first place. The same things that cause memory pressure in Java cause memory pressure in Go. Which is what I am saying and getting downvoted for my troubles--that there is so very little daylight between the Go VM (yes, it's compiled to native code, it still has a frigging VM, go look at its bogus ART with ALWAYS CAPITALIZED INSTRUCTIONS because Rob Pike and company think not-actually-assembly programming is a "fraught endeavor" and you can see it yourself) and the JVM that claims about performance are real, real sketchy.

I've been down this road. I've looked. I don't see it. Linking to corner-case proposals (again: good ones, but marginal) from Java architects who are in the unenviable boat of trying to create bullet-point equivalence between the JVM and the CLR--that's not actually an argument.


Thanks for the tip on the Trove library. Even though I hate the JavaXML language, the JVM is really hard to beat for long running processes on a dedicated server. And the kids gotta eat, so JavaXML it is...

(have an upvote from an otherwise Java lang hater for being convincing)

Aside: I propose renaming the primary language for enterprise apps to just one word, "JavaXML" (zha VOX em el), since the two are essentially inseparable anyway. I wish the other JVM languages would get more traction in BigCo development.


Please don't mistake any of this as defense of Java, I think the Java language is an inexpressive slog (though for my money superior to Go, the lack of generics really is that much of a problem when you write modular and composable code where the HTTP server is not the IPC layer). I use Scala or JRuby when I use the JVM, except when I need to know exactly what the compiler is going to be spitting out, like when writing performance-sensitive code. This is rare, and I think the last time I wrote any Java at all was in a Google interview where they wanted me to juggle byte buffers. I use Ruby for things I don't care about or where a type system actively works against me. I use Scala for things I do care about or where a type system can help me. I use C++ for things where a garbage collector is antithetical to my purposes. (I have some hope that Rust will be a good candidate to replace both of the latter.)

Though, food for thought: I have written a fairly decent amount of Java in the past, and in what I would consider "modern practice" it has very little to do with XML. With Play, Dropwizard, and similar, you have no obligation to put up with something like Spring herpderp anymore. Or even Maven; SBT or Gradle are fine.

.

Anyway--what grinds my gears, and why I posted at all, is that I have noticed in the Go community--not, I hasten to mention, enneff, as he said I think he and I are probably more in the space place than not--a really weird unwillingness to credit other environments for anything, whether from stubbornness or ignorance. If I can speculate--and I can--I think that comes from two places. I think one is the origination of many Go advocates being Python and Ruby, which are both former new-hotness ecosystems that themselves don't encourage breadth or depth in the programming languages space; in the Ruby community at least Java is often held as this inscrutable "enterprise" thing that can't possibly have any real benefits, and I feel like that's leaked into Go. The other is the cultural origination of Go in Plan 9--Keith Wesolowski's views on the second-system effects of Plan 9 and the epistemic closure and cult-of-personality effect of its developers and community are good ones and I don't need to repeat them here.

Right now, to me, Go is a mishmash of Java 1.3 and Java 1.4, right down to the overuse of green threads and the too-simple type system that forces you to trade safety when you want code reuse. And that's totally fine for people who like it. But it's nothing special, and the breathless hype around it from people who plainly haven't gotten their hands dirty with what came before makes me want to boil my head. Or their heads. After all, I like my head.


If you're mmaping a file and processing the majority of it, you really are typically doing that in C today if you care about performance. You can get acceptable performance in Java with ByteBuffers, but because of the lack of value types it doesn't feel like Java any more. Go should be able to get much closer to C's performance, while still being closer to idiomatic Go code. And Go can plug in small pieces of C code / assembler for the really performance critical stuff.

All this can be done with JNI, but JNI is so un-fun that I can see Go making big inroads here.


People use mmapped files all the time in performance critical Java. Typically using the unsafe packages. In fact, if you want to communicate with C/assembler level things, this is the way people who do fast Java do it because JNI is very slow.

If you want to use an abstraction around ByteBuffers that feels like value types take a look at the javalution structs.

As a counter to your argument, C# has had value types for quite a while and has not achieved Java levels of performance, so those in and of themselves aren't enough. Mostly thats because if you are doing any allocation in fast code you are doing it wrong regardless of language. Even in C object pools and arena allocation are standard for performance critical work. The gap between Java and C (or really C++) right now is almost entirely around control of the memory model, not allocation (that said, I'd love the JVM to have value types and am glad that go started with them).

If anything will allow go to achieve better performance than Java its that it will be able to incorporate the lessons learned from Java without the support burden. I do think the constrained nature of go will give it a very good chance at impressive performance.


I don't think C# vs Java performance can always be directly compared.. C#'s SuppressUnmanagedCodeSecurity attribute for PInvoke interfaces, when you can use it, reduces C#'s call overhead to something like 20% over using a Managed C++ library as a bridge. If you don't need to pass complex numbers (doubles) it isn't bad at all. Just depends on your needs.

Then again, depending on your needs, being able to scale out or up is far more important than raw performance characteristics... just depends on your needs.


That is exactly my point. Value types vs lack of value types is largely immaterial to the performance story.


JNI is un-fun, so JVM developers are working on the solution. I think Panama will arrive sooner than Go making any inroads.

http://openjdk.java.net/projects/panama/


Good thing. Though Go made inroads in all kids of Web / Cloud infrastructure considering Java should be the first(only?) choice with production grade application servers etc already present. I think Panama shows Java was late to realize that native code easy access is getting more important for Java even with better hardware.

Where I work ~16GB Java heap makes gc pauses huge and unpredictable. I think Java performance is great in benchmarks but the way code is written in most enterprises Java is hugely memory hungry and slow.

IMO Java position remains secure till management is on Java side. Technical merits limit to evaluating different Java technologies not Java vs Non Java technologies.


Just curious but why would the same type of programmers that make Java "Enterprise" do better when given GO instead? Taking into account that GO GC is not better than the Java ones, and you currently can't solve it by trowing money at it at all either. e.g. No Azul Zing or IBM Realtime.

Lets be honest here, seeing the popularity of Ruby a few years ago we know that performance is not all either. And knowing were Java was in 2000 we know the same ;) First languages need to be used and then they get fast (even if it takes quite a while before that is true).


Doesn't Go have the potential to be faster than Java since it's compiled to native code (rather than compiled to byte code)?


JIT has potential to be faster than compiled native code. Better runtime information. Compiled code needs to cover all potential options and this means more instructions to execute.

Say a variable value is set through a command line option to be a certain value. Compiled native code has to assume the value to be dynamic, but a JIT can optimize it away, effectively hardcoding it for that particular invocation. Same applies to more complicated type of software. Some configuration and invocation parameters tend to be effectively static during that particular invocation. JITs can capitalize on this fact.

JITs have also better chance to adapt to exact hardware it's running on. Compiled code is forced to make one or a limited number of assumptions of available CPU hardware configuration.

In the end, both options are running compiled native code. JIT just does it a bit before running.

Of course current reality is the opposite, but the key word here is potential.


I'm glad you emphasized potential and mentioned reality.

One other aspect that has become increasingly important is power consumption and heat. Huge data centers now have to worry about enormous electricity consumption and keeping all the equipment cool. JIT code must do more work to compile (and recompile to optimize) on the fly which means more power and more heat.

On the consumer end, Android just switched to Ahead of Time compilation instead of JIT because its JIT performance wasn't that good and it required more power thus sucking battery life.


Same on Windows Phone. .NET is also compiled to native code ahead of time.


Thanks, that's a very clear (and thorough) explanation.


There are quite a few JVMs that allow compilation to native ahead of time.


Java is also compiled to native code, but only after it runs for a bit.


Android does AOT compiling with ART, it became the default in Lollipop.


Android does the right thing for a transient GUI client program on a device with little memory. HotSpot JIT does the right thing for a (long running) server program on big, dedicated, hardware.




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

Search: