Hacker News new | past | comments | ask | show | jobs | submit login

It's not really "go" that makes the difference. it's how the runtimes and frameworks are used and/or made.

frameworks on top of frameworks, all being over engineered, with poor understanding of what the system actually does, result in super slow apps on top, that you generally go to aws to scale.

It's not the first time that I see people reducing a dozen servers that were "always maxed out" by a couple of servers "that can barely feel the load".

Yeah throwing hardware at the issues is fine'n all but we're been way over the limit too many times in too many directions.

Go provides a clear start/APIs/framework, and the language enforces good habits. Also, it doesnt have things like global interpreter locks.

The lesson? Stop using cool techs because there's blogs about them. UNDERSTAND the tech before using it.




I'm very sympathetic to your tech-on-tech-on-tech-on-tech hogwashery promulgated by open sourcers & vendors prosteltyzing their wonderful solutions and the other acculturation factors that permits developers approaches other than trying & seeing & exploring-

That said, you are wrong.

I'm not a Go user and I don't care for it, but Go is fundamentally different and better than most runtimes. Go has it's own green threading, which allows it to start new tasks using extremely small amounts of memory, and it can switch between tasks without the normal cost of context switching full on threads.

That is a huge difference. Node has some elements in play here, with it's event loop and callbacks, but really the only thing in the field that compares to Go that's in use is Erlang, and there's no frameworking on top of Erlang that wouldn't cause most PHP or nine tenths the Python developers to curl into a weeping ball at the Eldritch horrors they'd been exposed to: even ASM code is not nearly so effective, being clearly a low level somewhat harmless thing.

Being able to kick off small processes, that can sit around for a really long time, awaiting data- that's a model of computation we haven't done in decades, never with the mass popularity- there's a TLA for this kind of processing- Communication Sequential Processes, and Go is it. It's entirely different from the procedural model, from the Python and Perl and PHP scripting, where concurrency is a carefully waded into thing- Go is a concurrent first runtime, about ongoing, enduring, concurrent processes, and that's huge, HUGE I say, huge.


> I'm very sympathetic to your tech-on-tech-on-tech-on-tech hogwashery promulgated by open sourcers & vendors prosteltyzing their wonderful solutions and the other acculturation factors that permits developers approaches other than trying & seeing & exploring-

Are you studying for the SATs, or just trying to make your argument sound more compelling through the use of unnecessarily complex words?


Yet, different, and sometimes more complex words can have entirely unlike connotations, that much more effectively describe the message the author is trying to convey. Sometimes, simpler words are just that—too simple to properly describe the concept the author would like to capture, and the emotions he would like to encode within it.

That's not to say complicated is always better. Like it programming, the best set of tools are those suited for the job.

In the end, you consider your audience. Can I add more to this sentence to better capture the feeling I'm trying to convey, without detracting from it's ability to be understood? The parent most likely decided that on a forum like HN, the answer was yes.


It's how I feel, I'm so very very sorry it's tripped your acceptable tolerance levels. I'll bite my lip and not add "you prat" to the end. Thanks for your considered moderation, and I see your point.


My only point is that being obtuse is not the best way to get your point across. I assume your goal in expressing your opinion is to convince others, and to do so it helps to be clear, concise, and direct.


That's a very narrow assumption as to why someone would express their opinion. The OP might be sharing their experience (in what was a humorous way) purely to be sociable in this discussion...

Not everyone is out to convince others.


Righto, he could be here to make himself feel good by using words he doesn't usually get to.


Dare I call into question what you are here for? How do you feel about your contribution- attempting to heap more shame- plays for the whole audience? Is what you are doing of value?


On a forum like HN, where the audience spends a great deal of time reading and engaging in self-improvement, choosing words that are not simplistic should be fine.


I'm going to go out on a limb and guess that even in a community where "acculturation factors" is something people actually say (crit lit? sociology?) it's something that causes people to play that community's equivalent of buzzword bingo.


Ia, Ia, Erlang Ftagn!

I agree though, I just wish that Go would have developed from Erlang as a runtime.

The Erlang virtual machine and systems are beautiful things - I used them for some wire-level work on a project and bitfields are awesome, and it provided a clean interface to a more 'normal' language to display to the user, fail-fast fault tolerance on a public safety project, neat stuff.

It's just erlang-the-programming-language that has all the Prolog warts that scares people, I think.


Per your queueing, I'll toss in the Elixer chip- http://elixir-lang.org/ - it's a rather rote, boring, routine language that we all can be semi familiar with, with some aberrations carried over - pattern matched dispatch is still there, for example, making people wonder wtc. The web-page highlights it's advancements, it's "features," which is mildly amusing to me in that the biggest draw is that it's an Erlang that feels familiar to us Algol-derived unwashed/don't-know-anything-but hordes.

Kind of as a foil to that normality, it's similarly remarkable to me that the Prolog asserted-messages/facts & reactive processing cycle of Erlang isn't itself better captured and shown off. It's kind of a middle stage introductory tutorial, after you've made it threw guarded dispatches, yet by itself I think it'd make a great "start with the hard stuff" intro-tutorial to Erlang, and I haven't really seen it presented independently, firstly.


> It's just erlang-the-programming-language that has all the Prolog warts that scares people, I think.

I must be strange but I actually like Erlang's syntax. Its pattern matching is really hard to beat. Also with Erlang, it is not just about the language unless one just wants to learn academic FP or Actor model concepts -- it is about the framework. Debugging, tracing, distribution all those come as part of the package.

Think of Erlang as a tank. It might not be pretty and slick as a new Mercedes, but when you go into some battle, you need to learn to operate a tank, a shiny Mercedes will only take you so far.


Another one here... I like Erlang's syntax as well. Of course, we could have some things better (like record syntax), but it's really not bad at all.

I think most people have curly braces fetish (we call them "tits" at times where I work). If it doesn't have "tits", no thanks, it's ugly and bad.


There is talk about frames and maps for a while. I noticed there is an upcoming Erlang factory talk from Ericsson about this feature. I suspect those might end up used in place of records in some cases.


Correct me if I'm wrong, but the Haskell concurrency model is a very efficient one which is also based on lightweight threads. Moreover, is CSP is all you care about, you might want to have a look at CHP.


Go is... fundamentally different than most runtimes? Probably. Better? Maybe. Better than the comparable ones? I think it's losing that war. You don't even need a special runtime, it can help, but I think the amount it helps is overstated in Go's case.

Concurrency isn't that hard in practice. If you're willing to forgo automatic multiplexing Perl will give you Go's concurrency model in a library written ten years ago, and it works as naturally as it does in Go. Python seems to have similarly good support but it probably doesn't look much like Go. I'm not sure what Lua's doing these days, but in the past I've found concurrency dead simple. If you happen to be writing C, time-slicing the work isn't even that hard. If you know enough about Go's concurrency to tell whether a single goroutine will cause its scheduler to deadlock all by itself, you can easily write concurrent programs in all these languages.

I know this will be a controversial claim, but all of these solutions are easier to reason about than Go. Usually not by much, and it has primarily to do with the nature of its multi-threading support, but that's just the concurrency model being weakened by the support for convenient parallelism.

There is a case where Go is best: when you like writing Go more than the others. You can guarantee a little less about concurrency than most, but at least you can usually guarantee more about types than most. If you like writing Go you will either luckily avoid the problems or develop habits that prevent you from producing concurrency bugs, possibly even without realizing it.


Go's standard lib is built around it's communications and concurrency primitives. Sure one can extend other languages with new capabilities to take them into Go's realm, but that implies a movement away from stock standard core, whereas Go users, at their core, share a common massively concurrent message passing beast of a runtime and a concurrency friendly standard library that they are all unified behind. One will never mobilize behind a concurrent library in the kind of ways doing it up front will accomplish. Go has a large community of practitioners all writing massively concurrent code. That is huge and has never been done before.

But let's go look at patterning: look at Node: everything is hinged around re-using Node's core patterns, callbacks and every now and then slower events. There is promises work abound, but it's not used heavily: indeed it'd be hard to, with intermodule work, because A) it's not the standard lib B) nor are promises standardized. People seem to prefer something I loath- the horrible Async library- which gives them a bunch of composition tools to make worse the awful awful crime that is callbacks: because callbacks are what Node is, people pick up tools to do it more, to a further extreme, rather than going to the foundation & reshaping the landscape. (PS: Callbacks are A) awful B) actually & entirely the right decision.)

I was reasonably seriously into Perl, but I don't know what perl CSP style library you seem to be alluding to that A) you seem to indicate people used & B) got on par with Go 10 years ago. But I'm interested to hear of it! <3 me some CSP.


> but that implies a movement away from stock standard core [...] never [etc.]

I wouldn't have said anything if I didn't disagree very strongly with these sentiments (see below about growing your own CSP/etc, and later about Coro in particular.) But first, about Node: let's not look at Node (unless you really want to, but as long as you understand it has nothing to do with my comment.) Problems with JS are usually founded on people complaining they don't like callbacks (translation: "Go is better because I like it better"—in which case please dispense with the cognitive dissonance and just be honest and say as much♯) and are inapplicable to other most other languages regardless.

♯Edit: That's not necessarily directed specifically at you, but people often vilify every aspect of things they don't like. I'm not convinced that's what you're trying to say about JS.

I don't view concurrency as this mysterious thing, if you know CSP you can write it in any language, usually fairly naturally. In languages like JavaScript, Perl, Tcl, you can even make it look like it was already part of the language, tucking away calls to the scheduler so the user doesn't need to write them explicitly (heck, you can do that part in C... but... don't), like in Go (save for pure-computation loops, also just like in Go.) All Go really does over the general case is adding implicit calls to the scheduler (not nicely possible in some languages) and treats the scheduler as a second-class primitive feature.

To go on about a unified implementation reaches my ears much like an argument that you'd better use `for` loops and never `map`s (guess what you can't do in Go.)

I wasn't going to bring this up, but since you're familiar with Perl you will be less likely to assume limitations. The lib is Coro. People do use it, but it is controversial because of #dramaintheperlcommunity (#whatelseisnews.) I don't know how popular it is overall, but if popularity is an issue for you let me know because it's a stupid argument to get into and I don't want to have it without realizing it. People rarely pay attention to concurrency anyway, but it's been around forever.

It is not a parallel library, for which I am thankful. (It's not incompatible with parallelism, and importantly: it doesn't make Go's mistakes in that area.) It amounts to a scheduler, facilities for spawning coroutines, wrappers to make calling the scheduler implicit (eg. at IO points), do async IO and every single thing you would need to make Perl automatically do the things Go automatically does. It will look exactly like Perl with Go's concurrency model, in broad strokes you do the same things, in the fine details you use Perl modules and methods and a new keyword or two.


"if you know CSP you can write it in any language"

If you don't know CSP you still have no choice but to write it in Go: that the core unity I've been trying to describe, something the entire standard library is built around, like callbacks in Node. I don't see that you've added anything to your case for other languages in this recent reply: I think this excerpt captures well how your line of thought remains focused on what is possible, while ignoring my core arguments that it's all about the prime interface of the Turing machine before one, not what they set up for themselves on the machine.

"In languages like JavaScript, Perl, Tcl, you can even make it look like it was already part of the language,"

And newcomers may be able to immitate/cargo-cult your styling blindly without straying too far off the gods-sworn path if they are really lucky!

But rather than risk it, making a language CSP first would, IMO, be a clearer way to keep unity.

I really don't care what can be done with a Turing complete machine: I care what use of that machine looks like to the important audience: it's practitioners, all of them, practiced and experienced, and those with other backgrounds and seeking only practical results.

Go has created an entire language all of whose practitioners trade in CSP. I'm happy to de-rate from a language to a massively successful widely known active (let's say +30k active developers) shared and intercompatible practice of doing CSP (libraries or what not). Until I hear that challenged, my argument about Go being fundamentally different for having a runtime and standard lib based around CSP stands untouched, unless you have something specific there to contend.


And newcomers may be able to immitate/cargo-cult your styling blindly without straying too far off the gods-sworn path if they are really lucky!

I guess they should count themselves lucky if they know what an API is at all. C'mon this is a 101-level topic. You can't expect everyone to suddenly forget how to use an API (with or without native syntax) just because it's for concurrency... or do you?

As for Coro, it doesn't matter how many people use it, you can write the exact same things you would write in Go and it will work in the exact same way. It's not cargo-culting, it's writing CSP, which you still have to actually write CSP in Go if that's what you want, and it's perfectly possible not to.

The runtime distinction isn't very important either, in fact when I hear "runtime" I ask "why not library?" Some things are impossible in libraries but CSP is not among them, so I'm still asking "why not a library?" The scheduler, probably the most interesting part, can always be implemented as a library. Can you say anything particular to Go's runtime that makes it so special? I can't think of a single thing. The scheduler itself is about as boring as it gets. Not that there's anything wrong with that—it's not a difficult subject after all.

As for the popularity contest goes, we might as well be talking about an iteration protocol. There are many different ones but you'd rarely notice it. The most commonly used ones are relatively less-than-great. You can always use a for-loop like you can always write a coroutine or time slicer in the worst case scenario. It works, and very well.

The other thing is CSP. Up to now, I wasn't worried about the concurrency model in particular, but now you're saying we can't use actors, agents, etc.—it must be CSP. That's BS. CSP is nice when you have to build it yourself, but it's not all there is and it's no easier to reason about than other good options. In fact I would mostly only chose it when I had to build it myself or support for something else wasn't available, which is understandably common. Really though, this sounds like a deceitful way to rule out Erlang and friends.


    And newcomers may be able to immitate/cargo-cult your styling blindly without
    straying too far off the gods-sworn path if they are really lucky!

  I guess they should count themselves lucky if they know what an API is at all.
  C'mon this is a 101-level topic. You can't expect everyone to suddenly forget how
  to use an API (with or without native syntax) just because it's for concurrency...
  or do you?
Taking perl as an example, they probably know how perl does file i/o. Yet if we're switching to a concurrent system, the entire practice they have of doing file i/o needs to be re-grokked. Your proposal, that learning an API is all it takes to master a form of concurrency, is a fucking joke sir. Concurrency is greater than proceduralism, it shapes the systems of code whereas writing code and hitting apis is a lower order operation: shaping code.

  As for Coro, it doesn't matter how many people use it, you can write the exact same
  things you would write in Go and it will work in the exact same way. It's not
  cargo-culting, it's writing CSP, which you still have to actually write CSP in Go
  if that's what you want, and it's perfectly possible not to.
And how many CPAN modules can I download which I won't have to hand wrap in Coro? How many modules will expose coro based concurrency patterns?

I don't know about you, but most of my work is not writing code: it's using code. You miss this essential fact again and again.

What is possible is entirely not at all my interest here. I am interested in the practice of writing code. My sole contention against you is that the availability of libraries is irrelevant, an my basis for this point is that I agree with:

  The runtime distinction isn't very important either,  [[snip]]
Thank you for repeating what I said last time in a dumbed down way. I continue to agree we have Turing complete runtimes: we can do anything. Yes, the runtime distinction is largely unimportant (although performance, natch). Adoption is. Availability of code is. Having other practitioners is important.

  in fact when I hear "runtime" I ask "why not library?"
Indeed, you've done it three times now!

And every time you've gotten a response that agrees with your conjecture that it might be possible!

So why are you still making this same uncontested assertion!

So maybe you need to find something else to do, other than to re-describe how possible libraries make it to be Go-like or otherwise concurrent, because- with some niggling performance issues- there's been naught but agreement, and you've avoided clashing every time with my fundamental point that Go has a practicing community with some many thousands of libraries written for it, and the libraries you are talking about don't, and using your libraries will create a schizm between you and the other practioners of the parent language and the modules written for it, and Go users have no impedance when working with one another w/r/t their concurrent systems.

  Some things are impossible in libraries but CSP is not among them, so I'm still
  asking "why not a library?" 
FFS I ended my last post with a Turing equivalency argument that could not have been more explicit about agreeing with you. It's not about what is possible, unless you are a god and live forever and don't mind doing it all yourself. If that's in fact the case, fuck you, I'll see your ass at the fucking fields of Ragnarok. Now get off my lawn or start saying something you haven't that might be useful.

  The scheduler, probably the most interesting part, can always be implemented as a
  library.
Yes, Turing completeness. Good and acceptable performant? Meh, maybe, often actually, sure. I really could care less: I think you are so very far off in the weeds trying to discuss this, as what can be done is the most irrelevant topic when dealing with Turing machines, aka programming languages.

  Can you say anything particular to Go's runtime that makes it so special? I can't
  think of a single thing. The scheduler itself is about as boring as it gets. Not
  that there's anything wrong with that—it's not a difficult subject after all.
You are a masterful troll sir. The runtime itself is not novel. The important thing I highlighted from the beginning about Go is that its standard library is written for a distinct communications oriented set of concurrency primitivies, and thus all uses of the language flow from this reference library's standard, and that creates an interesting practicing community of people all using the same communications oriented concurrency constructs. Thanks for making me spell out the value again, I hope I'm clearer this time.

  As for the popularity contest goes, we might as well be talking about an iteration protocol. There are many different ones but you'd rarely notice it. The most commonly used ones are relatively less-than-great. You can always use a for-loop like you can always write a coroutine or time slicer in the worst case scenario. It works, and very well.

  ???
The other thing is CSP. Up to now, I wasn't worried about the concurrency model in particular, but now you're saying we can't use actors, agents, etc.—it must be CSP. That's BS. CSP is nice when you have to build it yourself, but it's not all there is and it's no easier to reason about than other good options. In fact I would mostly only chose it when I had to build it myself or support for something else wasn't available, which is understandably common. Really though, this sounds like a deceitful way to rule out Erlang and friends.

  Please cite where I went hardline and demanded CSP as the only acceptable communications/concurrency primitive I'll amend that such that your argument here is thoroughly unnecessary- I certainly don't see myself as opposing what you are saying, but you didn't actually tell me what the clash was that arose this contention- all you said was "The other thing is CSP. Up to now,"- and that doesn't actually inform me about what changed your mind, & made you think I was hardlining for any specific thing; so, I'm not sure how to clarify and reinforce my agreement with you, and my willingness to embrace any practioner's use of good solid helpful concurrency construct, be it of the communications variety (which I do myself enjoy, as concurrency in my artisan's mind is modeled as non-locality) or otherwise.


Taking perl as an example, they probably know how perl does file i/o. Yet if we're switching to a concurrent system, the entire practice they have of doing file i/o needs to be re-grokked.

I see you didn't look into Coro or read much of what I said. You do IO in the regular way and the scheduler is automatically invoked.

(If you want to know what needs wrapping, just use your head. If it does IO, make sure you have that kind of IO wrapper. If you screw this up your program will still work.)

You are a masterful troll sir. The runtime itself is not novel.

You yourself stressed the importance of the fundamental difference in the Go runtime, two or three times I believe. It seemed to have something to do with your argument against libraries.

The one argument you claim to have left (userbase) is the one you've been ignoring my comments about since the beginning. I'm not interested in arguing it anymore, but if you're interested in it, feel free to re-read my comments on that matter.


From the Coro intro docs-

Using only ready, cede and schedule to synchronise threads is difficult,

Coro supports a number of primitives to help synchronising threads in easier ways.

Coro adds threading to Perl but falls short of being a concurrency practice- it's tooling for doing concurrency.

Go establishes two fundamental primitives, goroutines and channels, and gets rid of old-worn notions of threads.

This isn't a novel runtime, because it's been done- in Newsqueak, just to name one- but the entire platform built from the ground up to be mobilized around not giving you the tools to find your own concurrency solutions, but to have a deliberated answer to all concurrency problems, a masthead banner saying "THIS IS THE ANSWER" is the differentiation and novelness I'm ascribing to Go.

That approach, over our discussion, I've come to realize is more characteristic of the standard library of Go than it is the runtime. That said, you're holding my feet awfully cruelly to the fire and I take issue with you using this newly gained outlook in such a mean-spirited and cruel fashion to stab at me.

Talking with you is incredibly frustrating as you toss away my points with a single dismissing wave and do not cite material things; you pick tiny little fragments to quip at as springboards to launch into whatever you wanted to start talking anyways. As I said before, masterful trolling, it's very hard to hold a conversation with you. I'd beg of you to yield, because otherwise we might indeed find ourselves on the field of Ragnarok, at that end that never comes after all infinity.

You also seem very ill informed about Coro- which you champion-

Fortunately, the IO::AIO module on CPAN allows you to move these I/O calls into the background, letting you do useful work in the foreground

So, no, _You do IO in the regular way and the scheduler is automatically invoked_ is a bullshit claim; this has all the weaknesses of Node.js's event loop, and the need to write small things that yield, or here in Coro world, cede, regularly. And if you use a CPAN module that does block, you are toast, making this fundamentally incompatible with everything else ever done in Perl in a very serious way.

a simple module that implemented a specific form of first class continuations called Coroutines. These basically allow you to capture the current point execution and jump to another point is in no way a parallel to the runtime of Go because the stdlib of perl is not meant to operate in a non-blocking way, and Go is. That, I think, is safe to say.


You also seem very ill informed about Coro

On the contrary, I've used it. And Go. I know what it's like in practice which do not, and this makes your claims sound very ignorant to me.

So, no, _You do IO in the regular way and the scheduler is automatically invoked_ is a bullshit claim; this has all the weaknesses of Node.js's event loop, and the need to write small things that yield, or here in Coro world, cede, regularly.

This is proof of your ignorance. It isn't like working with an event loop (but it is compatible with them, ultimately giving you a better option for parallelism than Go.) I was going to mention how rarely `cede` is necessary, but I had honestly forgotten what it was called. You need it exactly as often as you need to write `sync` or whatever it is in Go. Seriously, you can write the exact same program as far as where and when calling concurrency facilities are and you will get the exact same concurrency profile in your program.

I'm not sure what you think the wrappers are for, but they introduce non-blocking behaviour into the library calls you make by, as I've said a few times now, invoking the scheduler—that's how this all works after all. There's no compatibility problem either, that's BS you came up with like just about everything else you've said about it.


Oh you've used it! Well, I take back all the other points I said! And the documentation from Coro that I cited explaining how it works, how it requires different I/O patterns, and that it's just a GOTO that doesn't do anything about synchronous long running code problems one might have when trying to interface with the rest of Perl! You're message is read loud and clear, I get where you are coming from now!


The fact is everything you said about it is wrong, and you drew the wrong conclusions from the docs. I would forgive a person for making that mistake from a lack of experience, but if you want to play it the other way I could just accuse you of lying.

The best part is when you say it's just a GOTO that doesn't do anything about synchronous long running code problems—how do you think Go's concurrency actually works under the hood? It works the same way—and has the same problem you describe.


_it's just a GOTO that doesn't do anything about synchronous long running code problems_

_how do you think Go's concurrency actually works under the hood? It works the same way—and has the same problem you describe._

I think Go, in most uses, makes use of a thread pool to decouple it's green threads from the OS threads such that a single busy green thread does not seize up the rest of the runtime, and I think Go manages the assignment of green to OS threads in a way that is hands off for the programmer and by default.

I also think one gets a runtime in Go where I/O is multiplexed on an event loop, such that most common syscalls a Perl program might make don't hold up execution, and are instead handled in a non-blocking way by default.

Please let me know what else I can clarify so that we can find agreement.


That's an acceptable approximation for now at least, although Go doesn't know which threads will hold up the runtime.

I'm not sure what's left to clarify on your part. I think you misunderstand what working with Coro is like. In practice the Perl code that holds up execution is the same code that holds up execution in Go, things like:

    while(1) { $i++ }
have the same problem in both languages. Throw a `cede` (or `sync`) on it and the problem goes away. Might want to unroll it a bit first.

I'm not sure what there is to agree on. I could perhaps eventually convince you that working in Coro is very much like working in Go, or you could do that on your own time if you really want. But you seem to have an issue with a concurrency implementation that isn't widely popular, and that sounds like a matter of taste to me. To my ears it sounds like an incredibly stupid thing to get hung up on—CSP is so easy—but if that's your bag I'll only ask you not to use it to convince me of anything.


It's like this-

Concurrency is the root of all code construction, at a more meta- level than writing code. Layering it in with libraries is feasible, but you've already imposed some structure from the code, then you're adding on top of that structure an underlying structure, and that's... well... that's something Go avoided doing.


You probably stopped at the half of my comment, because I did write Go had advantages (over the likes of ruby&friends anyway).

But it's the wrong way to think about it, that's why it's in the second half of the comment. Else, people will just use go because they're told it's the cool kid on the block. WRONG way of thinking.

That is all :)


"Also, it doesnt have things like global interpreter locks." is basically the only thing you said that is anything alike what I'm asserting. And it demonstrates a knowledge of a thing I contrasted Go against, without demonstrating knowledge of what Go is & why it is different. Further let me add that I don't think "clear start/APIs/framework" captures the essence at all; there is something deeper than framing and end users here- there is something deep in the bowels that is using the machine dislike how all else do, and that is sorcery that is deeply important.


Alright - note that I generally attempt to make one point per comment, hence the succint part on Go. Your comment goes deeper, that is good. I don't believe we have diverging opinions however, hence my reply, as you did write that I was "wrong". But being wrong is difficult if we (mostly) share the same opinion.. in my opinion ;-)

Now then again, I do believe a clean start helps, and it's very possible that I didn't properly "capture the essence" , or at least not well enough



They went from a language with a factor of forty cost compared to C++ to one with a factor of four cost. They saw a factor of ten improvement in CPU utilization. Seems like all Go really brought to the table here was speed. I don't see any evidence that its unusual features were a factor, besides its base-level increased efficiency.


Nice rant, and I mostly agree with it, but there are a few slow things about the ways that some languages are usually implemented that don't really have much to do with over-engineering. Let's take this line of Python code, for example, and look at how the CPython interpreter runs it:

    return x + 42
This turns into the following bytecode instructions:

    LOAD_FAST       0 (x)
    LOAD_CONST      1 (42)
    BINARY_ADD
    RETURN_VALUE
First we get the x variable from the local namespace. This is an array of PyObject pointers; the LOAD_FAST oepration simply does an array lookup and puts the result on the stack, incrementing the reference count. Pretty fast. Next is LOAD_CONST, which is even faster; it takes an already-allocated PyObject and puts a pointer to it on the stack, incrementing the reference count. BINARY_ADD removes two numbers from the stack, dereferences the pointers to get the integer values, allocates a new PyObject with the resulting integer inside, bumps up its reference count, decrements the reference count of the two operands, and pushes the result on the stack. Finally, RETURN_VALUE jumps back to the caller of the function.

In Go, the corresponding code would be compiled to two, maybe three machine code instructions. There are good reasons why Python does it this way, but it does suffer some inherent slowdown.


A more interesting comparison would be the PyPy-generated native code for the expression versus the compiled code from Go. Comparing an interpreter with a compiler is generally uninteresting; the compiler almost always wins.

If you look at the code that comes out of various modern JITs you often will find really interesting differences in the native code they produce, even for simple constructs like arithmetic. Type checks, barriers, bailouts, etc - in addition to more mundane differences, like one using SSE to do floating point and the other using x87, and one JIT having a better register allocator.


> dereferences the pointers to get the integer values

Doesn't it find a method of x that implements addition?


Nope! There's a branch in the interpreter that checks if both operands are Python's built-in int objects. If they are, and the result can fit in a C int without overflow, then the interpreter adds the numbers directly. This is by far the most common case.


How can the interpreter know, at bytecode compilation time, that x is bound to an int? Surely it generates two code paths, one for the "common case" and another for when x is a general object with an __add__ method?


The test is in the interpreter, not the compiler to byte-code. Every time the + is evaluated, the interpreter checks for the common case before resorting to finding the first object's method.


Okay, I think I get it now. The check you refer to is done inside the BINARY_ADD implementation. That's why the bytecode is the same for both cases. Am I right?


Yes, as you say, it's not known at compile-time and is checked at interpretation time, each time. http://hg.python.org/cpython/file/b49971a1e70d/Python/ceval....


Thanks. And wow, the CPython source code seems to be very much readable. I've been meaning to dive further into Python internals for a while, maybe this is the time to do so.


Interesting, thanks.


> It's not really "go" that makes the difference. it's how the runtimes and frameworks are used and/or made.

Exactly.

For the type of product they sell, if the processing time isn't pretty much all going to the actual running of the customer supplied job code and network latency, they're doing something very wrong. The language choice shouldn't be much more than noise in a setup like that. The framework choice, on the other hand... Rails is hardly well optimised for a high traffic API that can't readily be cached.

I've done queuing and job processing in Ruby. Spending 90% of the time in kernel space handling network traffic or waiting is not hard to achieve for a pure queuing server. If you add delegating jobs to external code to do the actual work, you should spend less time in userspace in the code actually processing the messages.

If language choice nets you more than 10%-20% in a setup like that, something else has changed beyond language.

And that's fine. But a post focusing on the language change then makes it seem like they didn't understand what caused the performance problem in the first place.


Maybe I'm just a new and terrible programmer, but I feel like if you wait to fully understand whatever tech is out there in terms of what to use, you'll never get started.


Let's be new and terrible programmers together, because I feel like the only way to fully understand whatever tech is out there is to actually use it.


In reality you have to follow the buzz in the tech to understand new technology. If something sounds like you could use it, take a few days out to toy with it. If you still want to use it, try it out for a small project and the rest will come automatically if it is the right choice.


> It's not really "go" that makes the difference

But from what I've seen and read about Go, it does seem to have things in it that do make a difference.

For example from day one Go was designed for with concurrency in mind and that's a big plus.

To see how this can help this Rob Pike video does a good job of showing off Go's version of concurrency:

http://blog.golang.org/2013/01/concurrency-is-not-parallelis...

Now, you can implement concurrency lots of different ways using many different languages. But I've used a lot of languages and I never seen concurrency done as easily as shown in that video.


> But I've used a lot of languages and I never seen concurrency done as easily as shown in that video.

So I take it you never used Erlang.


Erlang is big and complicated compared to Go. It's not easy, and besides it is functional (not easy) which already makes it unusable by 90% of people.


> Erlang is big and complicated compared to Go.

No. OTP is big (arguably), Erlang isn't even remotely. It's also completely irrelevant to OP's remark.

> It's not easy, and besides it is functional (not easy)

That doesn't make sense. What's hard in Erlang? That you don't have a for loop?


OTP is big an complicated... Erlang really isn't.




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

Search: