The State of Go
talks.golang.org
talks.golang.org
--------------
It seems like these people simply don't understand Github very well.
Can only view diffs on a single page (can be very slow).
Cannot compare differences between patch sets.
Accepting a patch creates a "merge commit" (ugly repo history).
Don't use the merge button, just add the requester's repo as a remote to yours and use your familiar tools. If possible and done, a fast-forward merge + push will also close the PR. Comments are sent as they are written; you cannot "draft" comments.
How is that different from pull requests via emails? (Also, on the website itself the comments can be edited.) To create a patch one must fork the repository publicly
(weird and unnecessary).
What exactly is weird about that? It makes it possible for the requestor to craft their changes with full control, without requiring upstream to give them write access. This point is just entirely nonsensical. In general, pull request culture is not about code review.
A strong claim, but one without any justification, and which is, in my experience, as far from the truth as possible.Edit:
In light of their complaints about the need to fork, i have to say that their current contribution process can in its entirety be described as weird, unnecessary and baroque:
I have no idea what they specifically mean, but I can tell you, that the github requirement of pr to come from public repositories on github is something that bothers me occasionally. There are lots of reasons why I may not want my github fork to be public or I don't want to have a github fork at all but do want to contribute to a repo hosted there. This is a distributed version control system we are talking about after all.
As for their claim about pull request culture, again I'm not sure what they specifically mean, but I find the github code review tools to be very rudimentary and suspect that lots of other people with experience with more sophisticated code review workflows feel the same way. Github is a great service for some things but it certainly is not centrally about code review.
There are lots of reasons why I may not want my github
fork to be public or I don't want to have a github fork
at allWhat am I missing?
I just ran into this issue the other day when I was using Node with a lot of dependencies that still haven't been patched for issues that cropped up in OSX Yosemite.
I've rarely had trouble with assuming master (or ideally a tagged release) on the original repo (not a fork) is the one I should be using. Assume all forks are forks.
In any cases where this hasn't been true, it's been clear to me the blame is due to poor release management (or poor communication of release management, which is the same thing), rather than somehow the fault of github's PR or forking system. Although you can hypothetically argue that certain UI's encourage poor release management and others support it, I personally have not seen this to be an issue in github's UI.
It's difficult for me to explain why I feel this way. The original stigma of 'fork' is definitely part of it, but most of it is just my distaste for visibility: it feels horribly immodest to associate myself with a project with which I probably have only a passing association. I can't defend my attitude, but it's probably worth noting that people like me (and apparently the author of the Go article) will be dissuaded if public affiliation is a requirement.
And i am even more grateful because it's truly a way i have not yet considered. See, for me github is a tool that i approach as dispassionately as my garage door opener. It is a thing with which i personally solve problems. Those problems are broken software or broken documentation. I use github to fix things. And i'm almost always doing so with a sense of nearly full confidence in that my issues or PRs will either fix a problem, or allow me to gain information so i can fix it. The only doubt i have is when i recognize the maintainer is not very skilled or otherwise mentally a little of the beaten path and might need some convincing.
The least concern i ever have is "someone might see what i'm doing", which is why i've ended up with 210 forks in my account. I didn't think that concern could ever be a thing since i started using Github long after the time when i last had reason to feel truly self-conscious about the code or documentation i'm creating, and you did remind me of the time before that point, so i can understand you now.
Maybe with time it will get better for you, maybe not. Please keep sending emails with patch files if that's what you feel most comfortable with.
And thank you. :)
The problem is, there are people for whom this really doesn't work well. Some might just personally feel uncomfortable about it. Some might be concerned about future career prospects. Some might be women, who are worried about online harassment. Some might be people with stalkers, who are trying to avoid any kind of traceable online public trail.
This whole "share all the things" mentality leads to somewhat creepy exposure of everyone's private lives to governments, corporations, the general public (which can act as a mob on occasion), and also specific private individuals who you might be trying to avoid exposing things to.
There are lots of reasons why I may not want my github
fork to be public or I don't want to have a github fork
at all
The authors of the Lua language develop in private. They like to experiment freely with ideas, many of which never see the light of day.They said if people saw what they were doing in real time, it would probably cause mass panic among the community. (Oh no! You're removing feature X?)
Actually, you don't need to do that. GitHub provides a special pulls remote "namespace" on the upstream repo, so you can add it as a fetch pattern to your .git/config like so:
[remote "upstream"]
url = https://github.com/neovim/neovim.git
fetch = +refs/heads/*:refs/remotes/upstream/*
fetch = +refs/pull/*/head:refs/pull/upstream/*
Then when you `git fetch --all`, you will have ALL pull requests available in your local repo in the local pull/ namespace. To check out PR #42: git checkout -b foo refs/pull/upstream/42It's interesting that other systems has a nicer implementation for it.
In Phabricator, it's:
$ arc patch D12345
and it checks out revision 12345 into an appropriately named branch.Thank you :D
Fwiw, of the six bullets, I see three which are clearly subjective, one which is a clear advantage of gerrit, and two which I don't really know enough about to refute.
When it comes down to build systems, I think it's very easy to spend a lot of time moving sideways or backwards - and if the tool you're moving to has deficiencies compared with what you had before, it can be very frustrating. Certainly, if the tool people want you to move to offers few advantages over your current infrastructure, a quick dismissal is reasonable.
Getting set up with their current contribution system might seem a little clunky, but I don't think it's particularly hard to do, and definitely seems like a 'run-once' thing. Once it's set up, it seems to integrate into a workflow well.
Their contributors will have their current workflows set up nicely - and unless github's issues system has compelling advantages, it's definitely not worth them switching due to the temporary loss in productivity.
With github PRs, notifications are sent as soon as you write your first comment; in systems like gerrit and rietveld (and email) they are not sent until the reviewer chooses to send them. This leads to either awkward interactions if you start replying to comments while the reviewer is still reviewing, or unresponsiveness if everyone introduces hysteresis to avoid this situation.
This is IMHO the biggest problem with Github PRs; I don't necessarily agree with the Go team's decision to abandon the PR system but on smaller projects I have pushed for rietveld over PRs for this reason.
1:12pm line 33: Why are you doing this?
1:13pm line 33: I see, sorry, ignore my earlier comment.
A system that lets you draft comments and then send them out in a batch can avoid a bunch of noise. On the other hand, though, people who aren't expecting it can get stuck with draft comments they don't send out.Imho, the end user should be able to choose between live commenting vs draft+send.
This is the smell of git plumbing again. Don't use the obvious UX that's been presented to you, do some other workflow that doesn't appear in the documentation.
(But I am entirely sympathetic to the opinion that git itself exposes too much plumbing and has a pretty baroque end-user interface for doing certain things. And it's also certainly legit to wish or suggest that _github_'s UI worked differently than it does, although the merge commits don't really bother me, and some people prefer them, it's a point of some contention).
Looking back at arguments people make about how to "do it properly", it looks like something is broken. Git is broken, maybe Github is broken, documentation, UI, marketing. Something is though. When an obvious UI element is there, seemingly designed to do merges, and then everyone says "no, no, do this other thing", like send emails, then rebase here on top of that, make a ref pattern in your ~/.gitconfig ...
(Does this really need to be said?)
As a funny aside, when Github breaks the thing to say is "I wish one day someone would invent a decentralized version control system" ;-)
On the contributor instructions: note that if you just want to use plain git (and not our git-codereview tool) then you can stop at "Register with Gerrit."
We created the tool to provide a more familiar review process for the people that used our previous system.
If we took your advice and used offline diff tools, etc, we would need a similar page explaining how to do all of that. None of this convenience comes without an up front cost.
My issues are two-fold:
You could have just said on that slide: "We want a central code review system, so people do not have to learn Git. Github isn't terrible, but Gerrit is much better."
Instead you ended up putting up a list of points that make github seem like some kind of fatally flawed thing, while frankly putting people off with inaccuracies/subjectivities.
Secondly, by not allowing things by github you're forcing people to learn something else. Most developers experienced with Git will also be very familiar with Github. You're telling those people to instead go and learn something else. That will result in some people deciding it's not worth the trouble. I'm fully aware it's up to you to decide whether you're willing to pay that price, but personally i find it a bit odd that you can't simply do both.
And as for, apparently, most of the documentation on your contribute page being safely ignorable: If that is truly the case, i recommend rewriting that to make it obvious, because right now it's anything but. :)
If the last bit is the only good thing that comes out of this, then i'll be happy.
Everything about the language screams of coming from minds who stopped learning new things in the late 90s.
Happy to engage in a discussion about modern software engineering.
Are you?
It does a few cute and clever things, but I totally agree with this slide deck's gripes. Email and GitHub are not really compatible.
When you live with that assumption, things like merge commits and pull requests seem silly and overkill since you live in the "patch is developed/reviewed in isolation" world.
Out of context these comments read like they're in response to a poorly written article with an inflammatory title like "Why GitHub sucks".
What do you think would happen if there was a slide that mentioned that the culture around UTF was mainly about misogyny so they weren't going to support it?
Drafting comments... if you want to draft comments, can't you do that in a separate editor? Better than relying on the browser as an editor.
I agree, though, the public repository requirement for making a PR is a bit awkward.
A pretty history is extremely important when you need to attract new contributors to your repository. I've maintained extremely clean git logs and extremely nasty ones too. New contributors are immediately turned off in the latter case, because a good developer will generally git log extremely early when discovering a new project.
If you're talking about merges into an outstanding pull request, then that's a non-issue because any changes will still show up in the diff against the target branch/repo.
Rust has an integration robot that does all the merges into master, that records who reviewed it, what the link to the PR (and the code review on that PR! it exists!) was, etc. It was a little weird as a complete newcomer not to see humans in the `git log --first-parent` view, but I really like it now, because if I want to know why some commit was merged the way it was, that discussion is recorded nicely. (The merge commit has the subject/body of the PR, which doesn't need to match the subject/body of any commit in the PR.) Compare with, like, the Linux kernel, where the best you can do is Google for LKML threads with the same subject line. There's even a convention of [PATCH 0/10] for summaries, but those summaries are nowhere to be seen in the git repository.
That's cool, but it's still constraining a flexible system away from someone else's preferences. I prefer "--no-ff" myself too, but think that's irrelevant.
If you pull rebase, then that merge commit will be whatever the author of the commit decides it should be.
If they currently have ten files open, the merge commit will be ten files, regardless of how connected these files are, which is a lot of noise. With a pull-rebase, when they are ready to commit, they will decide to break it down nicely in 2+3+3+2 files.
The only person who should decide how to merge their files should be the person that modified these files, not git.
"Can only view diffs on a single page"
You don't need to use GitHub to view diffs.
"To create a patch one must fork the repository publicly (weird and unnecessary)."
I don't think it's weird.
"Accepting a patch creates a "merge commit" (ugly repo history)."
You don't need to have a merge commit, although I don't think that creates an ugly repo history.
"In general, pull request culture is not about code review."
I have no idea what this means.
Although I agree, I don't think merge commits are ugly. I think people coming from SVN/CVS where history is strictly linear have this obsession with keeping it that way.
In fact I find lots of developers just have an obsession with "clean" history, and fetishes for particular tools. It baffles me.
This has absolutely nothing to do with those, especially since they didn't even allow cleaning up histories. There is one very simple reason for why some developers prefer a linear history of master:
It makes debugging very easy.
With branch merges, especially when the branch lines cross, or the merge is an octopus merge, the complexity of the code necessitating inspection to find the root cause of a bug straight-up explodes. Meanwhile with a linear history it's not only easy, but automatable to find a commit that breaks a thing.
I do realize that you may not have had the displeasure yet to be in the situation to learn these things. Please feel free to consider yourself fortunate, but please also do try to understand that the things i just wrote are in fact simple observation of realities.
Your condescension is only hurting yourself.
Frankly, i find your style of argument through implication, and through trying to disregard something because it doesn't fit your definition of truth to be much more condescending than anything i wrote before.
"Revision that were never built nor tested" is probably closer to the truth. Do you rewind through all your history and rebuild and retest every commit in a branch every time you rebase? Sure, they're similar, and you probably didn't mess up the merges. There's likely no subtle lingering bugs that QA's only going to catch weeks down the line. Probably.
> then you may end up in a mess, but it's your fault. Code review is a thing that is done for a reason.
Sure. But I've missed so many things in code reviews, had so many things in my own code missed in code reviews, and generally make mistakes and messes.
I do agree that simpler branch topology tend to be easier to reason about. But branches do have their advantages... and I've also found that preserving the original branch topology has helped me untangle merge mistakes that were missed, committed, and then only discovered a year or more later.
Yes.
Me either. To me, the entire point of pull requests is about triggering (code) reviews. If I don't want to bother with review, why not just grant direct push access and skip the rubber stamp ceremony?
If I don't trust someone enough to grant write access to my repo, I certainly don't trust them enough to rubber stamp their pull requests.
Companies/organizations have different requirements for code reviews. Yes you can review code in pull requests, but in my opinion, it was not built for code reviews. In my previous company, we had a very rigorous code review process, which includes pre and post commit code reviews. We used Collaborator[1] and ReviewBoard[2] for code reviews and I totally understand why the Go team would use Gerrit over pull requests for code review.
[1] http://smartbear.com/product/collaborator/overview/ [2] https://www.reviewboard.org/
I've seen GitHub take five seconds to render a 100K line diff. In my experience all of the other tools I've used, including some of the ones listed, can take longer to render individual file sections of such a diff. It's fast enough.
Comments are sent as they are written; you cannot "draft" comments.
I'm a bit puzzled as to why you would need to draft comments inside the PR interface, especially in light of the fact that they can be edited.
Cannot compare differences between patch sets.
You most certainly can. Just use branch/revision compare.
To create a patch one must fork the repository publicly (weird and unnecessary).
Also immaterial.
Accepting a patch creates a "merge commit" (ugly repo history).
This comes closest to being a legitimate complaint. Because GitHub emphasizes recognition of contributors, it doesn't let you rewrite the commits in the PR as you merge them with the merge button, but there are multiple ways to merge on the command line that avoid the merge commit and play nice with the PR.
In general, pull request culture is not about code review.
WTF?
Sounds like a strong case of NIH.
This scenario happens often: I read through a change, making comments as I go. Then I reach some part of the change and realise "Oh, that explains why they did that in that other file!" So I go back and delete or alter my comments.
In Gerrit or Rietveld, the reviewee never sees those earlier comments.
On GitHub, the reviewee has already received the comment notifications and started responding before I have a chance to make the changes. The reviewee wastes time responding to questions to which I already know the answer. It's clunky, inefficient, and unnecessary.
It seems like you haven't used a tool like Gerrit or Rietveld. You should check them out.
I'm shocked at how bad Githubs PR review UI is given how much funding they have had for so many years. Even abandoned side projects like Rietveld have vastly better review UIs and workflows for larger patch sets.
Everyone is happy.
I use github every day for work. There are lots of things it gets right. But if you want to work on a project where you more or less have a central repository, take contributions from external and internal contributors, and have a strict policy of pre-submit reviews for individual commits to master that vary in size and complexity, then you want a tool that is 'code review centric'. That is, something that supports comment drafts, back and forth exchanges across many files, and notions of iterations as the reviewee responds to feedback. Github is lacking in this regard, for all the reasons the Go team pointed out. I mean... they just recently shipped side by side diffs!
The main thrust of my comment was to point out that lots of people in this thread are criticizing the Go team's choice to use Gerrit instead of Github, and the points they make seem to stem from an ignorance of both tools like Gerrit, and of workflows that work well that aren't pull requests. It's a bit of "what you see is all there is" where all they've seen is Github. And statements like "github is good enough" seem overly dismissive of the decisions of a lot of very smart people on the Go team.
For folks that are familiar with Gerrit and still poopoo their decision to use it. Well... we can agree to disagree :).
I'm rooting for Github. I want to see it get better so I can stop running a separate code review tool for my own projects! But it's got a ways to go still.
Our team is currently using Rietveld. But I've used Gerrit in the past, as well as internal tools of the same flavor back when I was at Google.
I don't particularly love Rietveld. But it's simple to maintain and does the job. That being said, I'm genuinely looking forward to one day being able to just use Github for this.
FullStory looks awesome, BTW, I just wish I could afford it.
Also, I'll definitely have to check out Reviewable!
I think GitHub and to a lesser extent Phabricator have enormous UI/UX upsides over Gerrit and Rietveld, which perpetually look like internal tools that never underwent proper UX review. What's more important is that GitHub has done so much for open source software and has achieved such critical mass that a decision to not use it now starts to also shut you off from a population of developers for whom the activation energy is too high.
Although it would be nice to have a 'Send All Comments' button at the bottom of the commit page so you didn't have to click through them one by one.
If that is available for general Java code (i.e. uses JNI) and not just for Android, that could be really huge for Go. Writing performance-sensitive low-level code in Java is still fairly painful, wheras Go still isn't great for writing big programs. I can imagine (for example) Hadoop, Lucene/Elasticsearch and PrestoDB all using this.
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.
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.
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 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.
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
(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".
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 .
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).
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.
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.
Not as impressive as it sounds. Most of it is cached in memory anyway...
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.
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 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.)
> 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.
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.
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.
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.
(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.
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.
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. 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.
All this can be done with JNI, but JNI is so un-fun that I can see Go making big inroads here.
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.
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.
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.
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).
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.
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.
But to each their own -- I'm curious what alternative system (if any) of accepting patches they have. If it's emailed git patches on a listserv, then I would definitely find it a barrier to submitting patches, myself, compared to github PR's.
I think in general, github PR's have proven succesful at soliciting code contributions from a wider field, which seems to be the goal of their UI (over command line git itself). Of course, this can seem a downside too, as committers have to spend time dealing with those submissions.
This is not true. There are many projects on GitHub which do extensive code reviews on pull requests. It may not be as nice as Gerrit for the type of project like Go (where you often have many iterations or the diffs are large). But for many other projects the UI that GitHub provides is sufficient (and arguably more efficient than Gerrit).
In general, it's poor form to send massive commits anyway. Those poor reviewers!
GitHub is painful for non-trivial reviews. Biggest WTFs:
- No comment threading (or at least collapsing). On a PR with 100 comments[1] it is unlikely that those revisiting the thread need to see (and download, and render...) the first bazillion comments.
- Source "annotations" are lost after a force-push (why not keep around a read-only view of old comments? We have lost some valuable discussions on GH pull requests)
Yes, we try to keep PRs small. But they also need to be meaningful, and sometimes they require (many) more reworks than expected.
That may very well be the case. But note how you said for non-tivial reviews, whereas in the presentation about go they said in general (see the line I quoted in my original comment). And argue that the vast majority of pull requests on GitHub are simple ones which don't need much discussion, so in general the GitHub UI works just fine. I don't have any hard numbers to back up my claim.
Right. And what you say validates my exact point: "pull request culture is not about code review." If all you want to do is cast your eye over it and click "merge", it works great. That's not how we work, though.
Yes, that is incredibly annoying. I discovered that if you add your comments in the "Files changed" tab (which shows the diff of the entire pull request) instead of the "Commits" tab (which shows the diff commit-by-commit), then the comments aren't lost when you force-push.
Just FYI, might make life a bit easier if you're stuck with Github.
Go binary size is a non-issue for most software. The java-rewrite I mentioned above went from a 80MB or so binary, to a 8MB executable. That said, there's been a few occasions when I've really wanted to use go for an embedded project, but couldn't due to it's size.
I read somewhere, someone said of go, "you'll come for the concurrency, but you'll stay for the interfaces. This is very true for me.
Generics. Go's red herring. Sure, there's been a handful of occasions where generics would have saved me some boiler-plate, but it's not been a pain point for me.
Tooling, from fmt, vet, to unit testing are all first rate. However, I wish there was a better debugger option for go. I know that gdb works with go (and with a great deal of difficulty if you develop with OSX) but I'm probably not alone when I say I really dislike GDB.
Overall, I've found the community to be friendly both online and in person.
As an aside, I've noticed much of the recent vitriol towards Go seems to come from the Rust crowd which I think is too bad. I enjoy both. Languages are not a zero-sum game. Who knows, the hate means Go has finally arrived.
I can't however find any instructions how to download and install them. Anyone able to help me?
go get golang.org/x/tools/cmd/callgraph
Or similar for any of these commands: http://godoc.org/golang.org/x/tools/cmdThe idea is to expand/collapse files, store progress of the review and collapse status of the files in local storage of the browser, so you can stop and resume at any time (I also have in mind serializing this stuff into a hash in the URL so you can forward it to the other machine for instance, and recreate the progress there).
I work on it every now and then and have a number of items in the backlog. If someone is interested to contribute I'll be happy to accept pull requests (sic!) :)
A lot of people seem to here insist that this is somewhat even remotely true. This is not. Look through Docker's pull requests on Github, look at their CI hooks.
Not sure why this is "insane."
Git is powerful because it was written with the ability to merge trees. The cherry pick workflow is throwing all of that in the trash. Why not use SVN at that point?
Because of cherry picking in Gerrit, dependent patches are a nightmare to maintain. Say patch c depends on b, which depends on a. Now say that patch c requires a change that merged into master. Because you can't merge into your development branch, you have to rebase c AND b AND a. This really pissed of the owners of b and a because it shows up as a new changset and wipes out votes. God forbid you depend on two different patches that each have separate dependencies.
You can use the merge commit to add the review information if you want. Then you don't have to molest the code change commit.
Our general workflow for the Go project is to review single commits, and sometimes do major new work in feature branches. When we submit a single change we cherry-pick. When we merge trees, we create a merge commit.
We don't write commits that depend on other pending work. That's overly complicated (IMO) even if you always use merge commits.
Imagine you are developing a plugin framework for something and would like to develop a reference plugin at the same time to flesh out the API. Neither belongs as part of the same change but the plugin certainly depends on the framework. This is basically impossible in Gerrit because of the awful way dependencies work. The only way it can work is with a feature branch, which is basically giving up on Gerrit anyway and using git in the way it was intended.
Gerrit ultimately becomes a choke point on the throughout a given project can have unless you have an extremely small set of contributors that can coordinate well (i.e. Not a large open source project). Maybe this isn't a problem for Go since there is a high barrier to entry for contributors, but it's something to keep in mind.
This is a boring conversation.
But I've just sent a change to add some help text to these pages: https://go-review.googlesource.com/4910
edit: The change is now live. No more easter egg navigation. Yay!
* See my mouse pointer
* Right-click and bring up the right-click menu
* Click on the link in the second slide
* Drag to select text
Chromium 40 on Linux
I think it's very fair to demand from a contributor to sync and build the entire app before they're allowed to submit a patch.
Interestingly, I note the Go team says it's "unnecessary" but doesn't provide their alternative.
Gerrit is the alternative used, and contributors have a full local clone of the git repo, with their commit, and that's private on their machine until they push it to Gerrit for review.
No-one said that that point alone is worth discarding the whole approach. You're nitpicking a single bullet point from around a half dozen points that stacked up.
Still producing 1.3M hello world executables.
I wonder if rewriting the linker from C to Go will be primarily rewriting, or maybe they will start fixing it somehow.
The linkers in the gc tool chain (5l, 6l, and 8l) do static linking. All Go binaries therefore include the Go run-time, along with the run-time type information necessary to support dynamic type checks, reflection, and even panic-time stack traces.
A simple C "hello, world" program compiled and linked statically using gcc on Linux is around 750 kB, including an implementation of printf. An equivalent Go program using fmt.Printf is around 1.9 MB, but that includes more powerful run-time support and type information.
diet gcc -o hello hello.c; strip hello
2280 bytes on my system.
There are reasons why using glibc results in executables so big, and why it is tolerated (kind of). Those reasons hardly apply to a new language being actively developed. Yet said language produces executables almost twice the size.
"Run-time support and type information", why is it linked into a an executable that never allocates memory and does no introspection of any kind?
fmt.Print does use reflection.
Besides, bickering over the size of hello world is pretty pointless; better to compare the size of programs that actually do something.
We do recognise that Go binaries can and should be smaller, but probably not as small as you might hope.
"You call that a big binary? THIS..." etc
I'm actually racking my brain for a case where a 500kb vs 5Mb binary would be a deal breaker, outside of embedded stuff I can't think of much.
One of the major blockers to clojure in android is that the lack of treeshaking/deadcode elimination makes for 10 second+ startup times in most environments.
"The ideal size is 10-15MB globally. Idea size for an app for tier 2/3 countries (like India) is below 5MB. 500MB+ is a non-starter. At 50MB+ the conversion rates fall off dramatically."
I don't foresee any changes on this regard at Google IO.
My point is, on typical machines today, even a 10mb binary is not an issue at all.
It is not about the size of hello world executable, that is just a symptom. A code smell if you like. There is something badly broken in the dead code (or dead data) elimination area. And I hope that code is in fact dead, because if it is not, add code generation to the list of smelly things.
What I suspect I see here is a kind of C++ vtable problem built deep into the language design somewhere. And the reaction is, let's talk about large executables so that it would kinda become not so visible. Or maybe let's take a look at glibc, because glibc is definitely a paragon of clear design befitting a new language.
> fmt.Print does use reflection
There are two problems with this. The lesser one is why does it need reflection to print a string. The bigger one is why do I see about 600 reflect.* entries in the resulting ELF instead of a single one for the string type.
It doesn't print just strings. It can print anything. http://golang.org/src/fmt/print.go?s=6420:6467#L221
After doing your research, you're welcome to submit a magical CL and PR that brings down the binary sizes, then you won't need to argue anymore.
The original link is titled "The State of Go". The first thing I want to know about a state of a new language is whether it works. Then how well it works. Then, maybe, how to fix it and which VCS to use. There is an issue I think is within the range of these two questions, but it is not even mentioned there.
So to make life a bit easier for people who like me expect that issue to be discussed first, I posted a comment summarizing (in my opinion) the state of Go.
My thoughts on how to fix it are hardly relevant to the current state of Go.
> It doesn't print just strings. It can print anything.
The fact it is just a string should be statically (build-time) inferable in a strongly-typed language. Reflection, at least as I understand it, implies run-time type information. So the question does make sense. Yes, I understand why it may be needed for a particular implementation of printf, this is why I called it a lesser issue.
Not trying to be rude, but your uninformed opinion is less valuable than you think.
There is definitely work that can be done to improve dead code elimination in the Go tool chain. The transition to Go will make this easier to achieve.
> What I suspect I see here is a kind of C++ vtable problem built deep into the language design somewhere.
Don't suspect. Dig into the problem and make some informed commentary. Idly speculating on HN is just spreading FUD, and benefits no-one.
You should read about Go's implementation of interfaces. It's not the same as C++'s vtable issue. http://research.swtch.com/interfaces
Statically. Care to check "ldd hello" of your binary?
In case you wonder, that's dietlibc which is typically built with no dynamic linking capabilities whatsover.
1.3 megabytes. That's like $0.00004 USD worth of hard drive space.
Does the go team think we are all rich or something?
It's a tradeoff, and worth it in my opinion.
% du -k eval/eval
2040 eval/eval
% strip eval/eval
% du -k eval/eval
1864 eval/eval
Don't just assume. Measure.Anyway it can be improved, but to me there are far more important things to be improved about Go than the binary size of small programs.
The code that actually executes is not bloated. It's not the most efficient code in the world, because the compilers don't have an optimizer as advanced as gcc's, but it's not unreasonably large.
To build gcc, you need a C compiler. To build Go, you need a Go compiler. To compile anything you need to start with some kind of compiler.
What happens if this catches on, and PyPy replaces CPython, and other languages do the same?
Hassles for those who prefer to install from source, and potentially a lot of duplication of effort writing compiler backends in every language.
In this particular case, though, I wonder why the Go team is planning to spend a lot of effort rewriting an already existing compiler. Rewriting a popular project from scratch can be a dangerous temptation.
Also, you don't have to download a binary of Go to compile the latest Go. You can download the Go source back when it was compiled by C, compile it, and then compile the later, Go-sourced versions, if for any reason you need to go that far.
http://golang.org/s/go13compiler
I don't understand your comment, because we already live in your nightmare scenario: http://en.wikipedia.org/wiki/Bootstrapping_%28compilers%29#L...
In practice, it isn't a big deal. When was the last time you worried about the language your compiler was written in?
> potentially a lot of duplication of effort writing compiler backends in every language.
That's also the state of things for every compiler that doesn't use LLVM or compiles to another language.
But the duplication of effort (which won't end when the "GoGo" compiler is ready to replace cgo), and a potential freeze in Go while "GoGo" catches up, are more serious drawbacks.
Yes, that is a trade-off other compiler teams have made, and it may be the right choice for Go as well, but it should be (and no doubt has been) considered.
Just because you can do the same thing in language X, doesn't make language Y obsolete.
Advantage of Go, for me, is less verbose code (implicit interfaces for the win) and a fantastic, stable and huge standard library. I also like the strict compiler, and that the language has a GC by default, makes certain things easier, and for most tasks I don't need the predictability that you get with manual memory management.
For my part, I like Go because it offers a great, if nascent, alternative to PHP. That's the gist of it, anyway.