News for hackers. Stuff that matters.
Re:Async-await on stable Rust by littlestymaar on Thursday November 07, 2019 @12:23PM (#21475125)
> Programming languages have the power to implement concurrency patterns that offer the same kind of performances, without the hassle.

Can you give one that reaches this goal? Go is often cited on that regard but it doesn't really fit your description since it trades performance for convinience (interactions with native libraries are really slow because of that) and still doesn't solve all problems since hot loops can block a whole OS thread, slowing down unrelated goroutines. (There's some work in progress to make the scheduler able to preempt tigh loops, though).

Re:Async-await on stable Rust by Felz on Thursday November 07, 2019 @03:34PM (#21476990)
I think Project Loom would fit. It's a remarkably sane approach:

https://cr.openjdk.java.net/~rpressler/loom/Loom-Proposal.ht...

Re:Async-await on stable Rust by ceronman on Thursday November 07, 2019 @04:03PM (#21477214)
As a Java developer I'm really looking forward for Project Loom. I think it's a great approach that avoids the pitfalls of the two-colored functions approach.

However, Project Loom doesn't fit into the "zero cost abstraction" paradigm of rust. Project Loom requires quite a lot of support form the JVM runtime:

> The main technical mission in implementing continuations — and indeed, of this entire project — is adding to HotSpot the ability to capture, store and resume callstacks not as part of kernel threads. JNI stack frames will likely not be supported.

It also still require manual suspension so JIT compiled tight loops will likely still cause a problem.

Re:Async-await on stable Rust by stuhood on Thursday November 07, 2019 @04:10PM (#21477282)
I think that that makes it fairly similar to Rust's approach then... compiler support for suspension, and cooperative scheduling.
Re:Async-await on stable Rust by pgt on Thursday November 07, 2019 @12:35PM (#21475242)
Clojure's pmap function (parallel map) is pretty cool: http://clojure.github.io/clojure/clojure.core-api.html#cloju...
Re:Async-await on stable Rust by ibotty on Thursday November 07, 2019 @01:51PM (#21476080)
There is rayon in rust land. This is a pretty different (simpler) thing.
Re:Async-await on stable Rust by fnord123 on Thursday November 07, 2019 @05:32PM (#21478011)
Rayon uses iterators. Iterators are the dual of first order functions. Iterators are superior because they are more general. (You can implement pmap using iterators. You cannot implement iterators using pmap.)
Re:Async-await on stable Rust by wwright on Thursday November 07, 2019 @08:54PM (#21479387)
Does Rayon use iterators, or just iterator-like combinators? I don’t think a for-loop would work with Rayon, would it?

You can also definitely implement iterators using first-order functions:

    const iterate = array => {
      const step = index => ({
        value: array[index],
        next: () => step(index + 1)
      });
      return step(0);
    }

    // add some combinators on top
First order functions can in fact implement anything if you’re willing to accept some bad syntax and speed — that’s the Church-Turing equivalence.
Re:Async-await on stable Rust by fnord123 on Friday November 08, 2019 @07:49AM (#21481738)
Hm. You're right. I hadn't used Rayon in so long I forgot it is indeed iterator-like combinators using an entry point called `par_iter`.
Re:Async-await on stable Rust by wongarsu on Thursday November 07, 2019 @02:56PM (#21476720)
Python's greenthread implementations are quite good, monkey-patching all calls to work asynchronously with low mental overhead and automatic library comparability (except for libraries that call native code obviously).

Of course Python generally fails to offer "the same kind of performance" for anything limited by CPU or memory, so it technically doesn't fit the description either.

Re:Async-await on stable Rust by bulldoa on Thursday November 07, 2019 @02:24PM (#21476416)
> since hot loops can block a whole OS thread

Asking as a beginner, what does the above mean?

Not sure what does hot loop means, and why does it block Os thread

Re:Async-await on stable Rust by brandonbloom on Thursday November 07, 2019 @02:41PM (#21476570)
Go creates the illusion of preemptive multithreading by having implicit safe-points for cooperative multithreading. Each IO operation is such a safe-point. If you write an infinite loop like `for {}` where there are no IO operations in loop body, it will block indefinitely. This will prevent the underlying OS thread from being available to other goroutines. The same thing can happen even if you do have IO operations in there, but the work being performed is dominated by CPU time instead of IO.
Re:Async-await on stable Rust by crawshaw on Thursday November 07, 2019 @06:41PM (#21478615)
Note that this is being fixed in the next release: https://golang.org/issue/10958
Re:Async-await on stable Rust by littlestymaar on Friday November 08, 2019 @02:08AM (#21480465)
That's cool it's finally coming, this issue is open since 2015! I wonder which performance impact this will have.
Re:Async-await on stable Rust by jdc on Thursday November 07, 2019 @03:28PM (#21476945)
Maybe this is a dumb question, but what if a language with implicit safepoints lets you opt out with something like a nosafepoint block/pragma?
Re:Async-await on stable Rust by wwright on Thursday November 07, 2019 @09:07PM (#21479440)
An “OS thread” is the most basic part of the program that can actually do things. When it is blocked, it can’t do anything.

OS threads can be expensive, so libraries try to only create a few OS threads.

A “hot loop” (usually, I think, called a “tight loop”) is a loop that does a lot of work for a relatively large amount of time all at once. Things like “looping through a list of every building an Manhattan and getting the average price over two decades.”

With some code like networking, you end up having to wait on other parts of the computer besides the CPU often, for things like uploads and downloads.

“Asynchronous programming” tried to make it easy to keep the CPU busy doing helpful things, even while some of it’s jobs are stuck waiting on uploads/downloads/whatever. This keeps the program efficient, because it can do a little bit of many tasks at once instead of having to complete each task entirely before moving on to the next.

The problem comes when you have a tight loop in a thread that is mostly expecting to be doing asynchronous work around I/O or networking. It is basically trying to juggle with one hand. The program can’t multitask as well, and you end up having to wait longer before it can start each piece of work you want.

Re:Async-await on stable Rust by staticassertion on Thursday November 07, 2019 @02:29PM (#21476465)
Hot loops are often "expensive", or where your program is spending a lot of its time.

If you're doing a hot loop, which may be synchronous, you will block the event loop attached to that OS thread, because a hot loop is presumably not yielding control until it is done.

Re:Async-await on stable Rust by bulldoa on Thursday November 07, 2019 @02:39PM (#21476548)
hmm, why is that a bad thing, if your entire thread is synchronous shouldn't it technically be blocking? Or is OS thread the main thread?
Re:Async-await on stable Rust by cfallin on Thursday November 07, 2019 @02:47PM (#21476635)
The problem is that the async model is a form of cooperative multithreading, so if one computation runs for a long time without returning to the main event loop, it can increase the latency for responses to other events. E.g., if one HTTP request takes a long time to process, and many of the worker-pool OS threads are handling such a request, response time goes up for all the other requests. OS-level concurrency is preemptive (timesliced), so one busy thread doesn't block other requests, but of course with much higher overhead in other ways. Best practice is usually to keep event handlers on event-loop threads short and push heavy computations to other OS-level worker threads.
Re:Async-await on stable Rust by bulldoa on Thursday November 07, 2019 @04:39PM (#21477590)
ah, that make sense, I think another user point out that spawning n goroutine does not actually spawn n physical threads but rather queue n task to m thread in the pool, so if we exhaust m thread, n-m task will be blocked.

Thanks for the explanation

I wonder what is the point where each trade off make sense (ie. what is consider heavy computation vs light computation, it probably is related to OS thread allocation time)

Re:Async-await on stable Rust by harikb on Thursday November 07, 2019 @01:43PM (#21476003)
> interactions with native libraries are really slow because of that

Can you explain a bit? What is the connection between concurrency implementation (which I am assuming you are talking about multiplexing multiple coroutines over the same OS thread) and say slowness in cgo? Having to save the stack? I don't get it.

Re:Async-await on stable Rust by yepguy on Thursday November 07, 2019 @02:49PM (#21476645)
FFI is slow because the main Go compiler uses a different calling convention than everything else. I couldn't tell you if or how that's related to its concurrency features.
Re:Async-await on stable Rust by bbatha on Thursday November 07, 2019 @03:01PM (#21476767)
Its an important optimization otherwise each go routine would use a lot of memory, but its not required. The stack allocation strategy has changed a couple times in main compiler, gccgo originally support it and CGo functions behave like normal go mod the stack.
Re:Async-await on stable Rust by sedachv on Friday November 08, 2019 @01:46AM (#21480408)
> Can you give one that reaches this goal?

First-class continuations. They are an efficient building block for everything from calling asynchronous I/O routines without turning your code into callback spaghetti, to implementing coroutines and green threads. Goroutines are a special and poorly implemented case of continuations. Gambit-C has had preemptive green threads with priorities and mailboxes at less than 1KiB per thread memory overhead for over a decade now, all built on top of first-class continuations.

http://www.iro.umontreal.ca/~gambit/Gambit-inside-out.pdf

Re:Async-await on stable Rust by Rusky on Friday November 08, 2019 @12:16PM (#21484325)
First-class continuations are too unrestricted to match the performance of Rust-style async/await.

If you take on a few limitations you can get there, but then those are exactly the things people complain about.

Re:Async-await on stable Rust by sedachv on Friday November 08, 2019 @03:09PM (#21486196)
It is worse than that. First-class continuations add a small overhead for stack operations, and they always have more memory overhead than callbacks/async transformation into callbacks. But the comment I was replying was about Go, not Rust. For the small overhead that first-class continuations have, they provide a simple and efficient way to handle coroutines, generators, asynchronous I/O, and green threads.
Re:Async-await on stable Rust by jsiepkes on Thursday November 07, 2019 @12:24PM (#21475141)
Erlang probably comes closest?
Re:Async-await on stable Rust by jabl on Thursday November 07, 2019 @02:30PM (#21476477)
Not an Erlang user, but my understanding is that the Erlang VM (BEAM) schedules on function calls. Which works fine for that use, since Erlang does looping with tail calls, but is not a solution for procedural languages.
Re:Async-await on stable Rust by dnautics on Thursday November 07, 2019 @10:36PM (#21479779)
Erlang vm is fully preemptive and schedules on something called a reduction. You can call an external function with EFI that can screw things up, but otherwise it's not necessarily on what you might consider a function call .
Re:Async-await on stable Rust by twic on Thursday November 07, 2019 @06:12PM (#21478320)
In practice, it's enough to preempt at potentially-recursive function entry and loop backedges. A thread which doesn't recurse or loop has to come to an end pretty quickly, at which point the scheduler will get a go.
Re:Async-await on stable Rust by floatboth on Thursday November 07, 2019 @04:01PM (#21477202)
There's no fundamental difference between inserting a yield before a tail call and inserting a yield before a continue statement or closing bracket of the for block, is there?
Re:Async-await on stable Rust by simcop2387 on Thursday November 07, 2019 @04:07PM (#21477255)
Fundamentally no, but it's a more difficult thing to do in practice at least. Unless you want to give up other optimizations like loop unrolling and other things like that since you end up losing the fact that the loop exists after some optimization passes.
Re:Async-await on stable Rust by findjashua on Thursday November 07, 2019 @01:55PM (#21476128)
BEAM (Erlang VM) provides pre-emptive scheduling
Re:Async-await on stable Rust by ngrilly on Friday November 08, 2019 @05:40AM (#21481166)
True for functions written in Erlang/Elixir, but not in NIF functions implemented in C.
Re:Async-await on stable Rust by unbalancedparen on Saturday November 09, 2019 @04:15AM (#21490493)
Thanks to dirty schedulers that is not a big issue: https://medium.com/@jlouis666/erlang-dirty-scheduler-overhea...
Re:Async-await on stable Rust by ngrilly on Saturday November 09, 2019 @06:19AM (#21490856)
Thanks for the link. It's a very deep and interesting technical post.