Live data from Hacker News

Coroutines for Go

research.swtch.com

81–90 of 191 posts

Re: Coroutines for Go

#81
post #35

Earlier quoted context omitted.

What is wrong with: for { next := getNext() ... } What is the advantage of writing this as: for next := range getNext { ... }

In practice the difference would be closer to: getNext := iterableThing.Iterator() for { next, ok := getNext() if !ok { break } ... } vs. for next := range iterableThing.Iterator() { ... } One advantage is that it's slightly shorter, which matters for very common patterns--people complain about `err != nil` after all. Another advantage is there isn't another variable for everyone to name differently. Another advantag…

I think more idiomatic go for the first case would be:

    getNext := iterableThing.Iterator()
    for next, ok := getNext(); ok; next, ok = getNext() {
        ...
    }
Which, yeah, the range cleans it up a bit, but it's not doing quite as much work as you're implying.

Re: Coroutines for Go

#82

I have written Go professionally for many years now and don't want to see it become something like the Python Twisted / Tornado / whatever frameworks. The go keyword nicely prevents the annoying function coloring problem, which causes quite a bit of pain. Sometimes in high performance contexts I'd like to be able to do something like e.g. per CPU core data sharding, but this proposal doesn't scratch those kinds of it…

> The go keyword nicely prevents the annoying function coloring problem FYI when you write a goroutine and have to use Context, that's literally just function coloring

Is it really? >90% of the time, I'm just passing a context so that I can cancel the rest of the goroutines if an early one fails and I don't need to do the rest of the computation.

That works just fine with throwing a context.Background in, which should be available anywhere, and not color the function.

Re: Coroutines for Go

#83
post #77
post #18

Earlier quoted context omitted.

"Enormous amount of overhead" is the operative phrase. In general, you want your concurrency operations to be significantly smaller than the payload of the operation. In the case of using channels as iterators with goroutines behind them, it works fine for something like a web page scraper, where the act of fetching a web page is enormously larger than a goroutine switch, but as a generalized iteration mechanism it's…

But if your iteration is so fast then you don’t need a channel at all. Just use a plain for loop.

Yes, that's exactly what the article is about: how we can model "plain for-loop" levels of performance in the presence of complex (intricate state at multiple levels and high potential for nesting iterators) code that is supplying the loop(s)

Re: Coroutines for Go

#84
Multitasking systems gave us processes.

But those were too much.

So we got threads, which are processes that share an address space, file table, and some other things. The scheduler can switch from one to the other more easily than between processes, and data can be shared between threads without needing serialization.

But those were too much.

So we got user space threads, which are logical threads of execution that are driven by a runtime entirely in user space. The runtime adds scheduling hooks into all I/O functions in the standard library, or even uses a system API like Unix signals to preempt logical threads. No system-level context switching is needed. User space threads can be tiny.

But those were too much.

So we got coroutines, which allow a programmer to define logical "threads" of execution that cooperatively interact with each other. There is no assumption about the presence of a scheduler. The programmer either writes their own event loop or invokes one from a library in a "real" logical thread.

I wonder what comes next. As far as [communicating sequential processes][1] are concerned, maybe cooperative coroutines are a low as you can go.

[1]: https://www.cs.cmu.edu/~crary/819-f09/Hoare78.pdf

Re: Coroutines for Go

#85
post #69

Coroutines are one thing that i'd probably prefer language support for rather than a library. x := co func(){ var z int for { z++ yield z } } y := x() for y := range x { ... } or something to that effect. It's cool that it can be done at all in pure go, and I can see the appeal of having a standard library package for it with an optimized runtime instead of complecting the language specification. After all, if it's p…

wow that is horrible. none of that is intuitive, which is one of Go strength. you would need to specific learn the Go semantic of coroutine to have any chance of writing or even reading code like this.

Re: Coroutines for Go

#87

Somewhat on topic given that OP brought up coroutines in Python: what resources have folks used to understand Python's asyncio story in depth? I'm just now finally understanding how to use stuff, but it was through a combination of the official documentation, the books "Using Asyncio in Python" and "Expert Python Programming", none of which were particularly good. Normally I'd rely just on the official docs, but the…

This blog helps me a lot about the motivation and underlying mechanism of python asyncio https://tenthousandmeters.com/blog/python-behind-the-scenes-...

Re: Coroutines for Go

#88
Reasoning about and following the control flow of the proposed code hurts me inside. If Go adds function coloring via (e.g. python's async and/or yield concepts), I'm out, because I don't want to use this, much less encounter it in the form of a bug in some library.

Java and C++ are largely inferior for my typical purposes, but at the end of the day they work fine and are stable in terms of direction, and don't tend to repeatedly bloat the language over pedantry. If you want top-notch performance, there's already C, C++, and Rust.

I am not a fan of the function coloring shit in Python and Javascript.

I don't want the kitchen sink!

Re: Coroutines for Go

#89
As a point of comparison, here's my demo from a recent presentation of firing up 1 million (1,000,000) Elixir (BEAM VM) threads, sending them all a "Hello!" message, and then each thread waits a random amount of time between 0 and 2 seconds to send a message back of "Process received message !"

At the same time, I am running the Erlang observer beside it to watch what happens to the CPU and memory consumption and how quickly it recovers/cleans up the garbage.

The biggest bottleneck here is the terminal's ability to keep up, but the observer seems to reflect what's happening accurately.

https://www.youtube.com/watch?v=yxyYKnashR0

The code I used: https://gist.github.com/pmarreck/4cc8f2f55a561ebce2012085a3a...

These features have been built into Erlang (and thus Elixir) since the 1980's. I'm sure many of you have heard of the Actor model and/or Erlang's "legendary" implementation of it, but I don't know how many have actually seen it in action with monitoring kit running.

I think it would be great for Go if it offered language-level support like this, but given the extremely resource-efficient implementation (both in spawning and runtime consumption) of threads on the BEAM VM, coupled with the ease of concurrency which comes directly from only permitting immutable values, I don't think it will ever be matched.

Post reply on HN