News for hackers. Stuff that matters.
Re:Fast, Safe, and Complete(ish) Web Service in Rust by masklinn on Tuesday March 27, 2018 @01:54PM (#16691045)
Really nice introductory article, though some of the more… axiomatic assertions, are iffy.

> If it’s possible to build more reliable systems with programming languages with stricter constraints, what about languages with the strongest constraints? I’ve skewed all the way to the far end of the spectrum and have been building a web service in Rust

Bit overselling it, that introduction would work better for something like ATS or possibly Idris. Rust has its strictness, but it's not exactly "you must prove this recursion terminates"-strict

> Synchronous operations aren’t as fast as a purely asynchronous approach

This is misleading. Synchronous sequences are generally faster than asynchronous ones because yielding and getting scheduled back has a non-zero overhead (this is regularly re-discovered, most recently by the developers of "better-sqlite": https://news.ycombinator.com/item?id=16616374).

Async operations are a way to increase concurrency when your synchronous sequence would just be waiting with its thumb up its ass (e.g. on a network buffer filling or on a file read completing), so you can provide more service over the same wallclock time by (hopefully) always using CPU time.

Re:Fast, Safe, and Complete(ish) Web Service in Rust by nordsieck on Tuesday March 27, 2018 @03:40PM (#16692029)
> Synchronous sequences are generally faster than asynchronous ones because yielding and getting scheduled back has a non-zero overhead

Indeed. I remember being shocked when I first read "Thousands of Threads and Blocking I/O" [0] by Paul Tyma.

After reading the C10k problem [1], I just believed that a big pile of threads would never work and never updated my beliefs. While such an approach is still quite memory limited compared to asynchronous approaches, it scales quite far and can have a very high work rate.

[0] https://www.slideshare.net/e456/tyma-paulmultithreaded1

[1] http://www.kegel.com/c10k.html

Re:Fast, Safe, and Complete(ish) Web Service in Rust by fafhrd91 on Tuesday March 27, 2018 @05:53PM (#16693089)
i'd say in most projects i worked, threads would be enough. but it is so boring :) new shiny async code is much more entertaining!

on other hand we should talk about C100k or C1m problems.

Re:Fast, Safe, and Complete(ish) Web Service in Rust by nordsieck on Tuesday March 27, 2018 @11:29PM (#16695017)
Someone actually coined the C10M problem a while back [0]. It looks like it hasn't been updated in quite a while, though.

http://c10m.robertgraham.com/p/blog-page.html

Re:Fast, Safe, and Complete(ish) Web Service in Rust by kitd on Wednesday March 28, 2018 @08:25AM (#16697138)
The problem is that, in practice, many of those thread contexts are holding open resources like DB connections or file handles, and the costs related to those mount pretty quickly.

This is why actor models are good IMO. They are based on the actual resource model, rather than the developer's mental model. That is, until the developer learns to change his/her mental model.

Re:Fast, Safe, and Complete(ish) Web Service in Rust by lomnakkus on Tuesday March 27, 2018 @05:26PM (#16692878)
Allow me to third that. It's one of dangers assuming that what you learned at university 15-20 years ago still applies. Another interesting talk: [0] (and even that is 5 years old)

[0] https://www.youtube.com/watch?v=KXuZi9aeGTw

Re:Fast, Safe, and Complete(ish) Web Service in Rust by nicoburns on Tuesday March 27, 2018 @02:10PM (#16691193)
In other words, for data-bound processing (such as most web services), async approaches are faster (specifically they have greater throughput).
Re:Fast, Safe, and Complete(ish) Web Service in Rust by lomnakkus on Tuesday March 27, 2018 @05:31PM (#16692918)
I'm confused about your "greater throughput" comment. Generally one achieves maximal throughput by maximizing parallelism (not plain concurrency!) and letting each individual core/CPU run its job to completion while ignoring everything else (even interrupts, as far as applicable).

Async is generally associated with lower latency.

Can you expound?

Re:Fast, Safe, and Complete(ish) Web Service in Rust by Chyzwar on Tuesday March 27, 2018 @06:35PM (#16693429)
You can keep pushing bytes as you get them from async operations. In my nodejs am making 20000 DB queries and I can push data to connected clients when any these get completed.

In the threaded code, you need to get a window of time and memory. In my Java, I have a max heap size of 8gb and I can maybe create up to 8k threads. When making 20000 DB queries only 8k is being executed where most of these are waiting for the query to complete or CPU time.

Re:Fast, Safe, and Complete(ish) Web Service in Rust by vbezhenar on Wednesday March 28, 2018 @02:26AM (#16695806)
You're wrong about thread limit. I can easily create 100k threads on my PC and it takes around 6GB memory (and I didn't even bother to investigate that consumption, probably I could do with less). 8k threads is nothing. And beefy server machine should be able to deal with million of threads (but I guess that's around practical limit).
Re:Fast, Safe, and Complete(ish) Web Service in Rust by Chyzwar on Wednesday March 28, 2018 @03:07AM (#16695997)
This depends on thread implementation and how much is allocated for the stack. Java will by default allocate 1MB, you can change that if you know what are you doing.

I know that you can have millions of M:N/green threads but these are different. In any case, you need to compete for memory and CPU time to execute.

Since not many people are programming in Haskell and BEAM languages my simplifications still hold.

Re:Fast, Safe, and Complete(ish) Web Service in Rust by vbezhenar on Wednesday March 28, 2018 @04:13AM (#16696231)
I'm talking about real threads, not green threads and I used Java for my quick test. Here's code, you can run it yourself. masklinn is correct about virtual memory, every sane OS will only use few kilobytes for short stacks.

    public class Test {
        volatile static boolean stop = false;
        static AtomicInteger counter = new AtomicInteger();
        public static void main(String[] args) throws InterruptedException {
            Thread[] threads = new Thread[100000];
            for (int i = 0; i < threads.length; i++) {
                threads[i] = new Thread(() -> {
                    counter.incrementAndGet();
                    while (!stop) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException ignored) {
                        }
                    }
                });
            }
            for (Thread thread : threads) {
                thread.start();
            }
            while (counter.get() < threads.length) {
                Thread.sleep(1000);
            }
            System.out.println("Threads are running");
            Thread.sleep(10000);
            stop = true;
            for (Thread thread : threads) {
                thread.join();
            }
        }
    }
Re:Fast, Safe, and Complete(ish) Web Service in Rust by masklinn on Wednesday March 28, 2018 @03:37AM (#16696103)
> This depends on thread implementation and how much is allocated for the stack. Java will by default allocate 1MB, you can change that if you know what are you doing.

Isn't that vmem? Unless it also writes to the entirety of that 1MB before starting the thread, it's not actually committed by default on most unices.

Re:Fast, Safe, and Complete(ish) Web Service in Rust by vvanders on Tuesday March 27, 2018 @02:15PM (#16691253)
> This is misleading. Synchronous sequences are generally faster than asynchronous ones because yielding and getting scheduled back has a non-zero overhead

To get a bit pedantic, synchronization introduces overhead. If you've got an 8-core processor running things async/parallel may complete faster since you aren't pinned to one core.

That said, it's much harder to get right since you have to deal not only with thread sync overhead but also cache/pipeline sharing and a bunch of other gnarly things.

Re:Fast, Safe, and Complete(ish) Web Service in Rust by sulam on Tuesday March 27, 2018 @09:15PM (#16694344)
Even without formal synchronization in user space code, context switches have overhead.
Re:Fast, Safe, and Complete(ish) Web Service in Rust by zzzcpan on Tuesday March 27, 2018 @02:43PM (#16691519)
No. Implicitly yielding and getting scheduled back is exactly what synchronous sequence is. And it cannot ever be faster than asynchronous, because asynchronous doesn't yield. Any "rediscoveries" are just mistakes due to lack of fundamental understanding of these things.
Re:Fast, Safe, and Complete(ish) Web Service in Rust by masklinn on Tuesday March 27, 2018 @04:02PM (#16692222)
> No. Implicitly yielding and getting scheduled back is exactly what synchronous sequence is.

Your asynchronous system can be descheduled by the OS on top of the stuff it does on its own if it runs on a preemptive multitasking OS or hypervisor, which more or less all of them do.

> And it cannot ever be faster than asynchronous, because asynchronous doesn't yield.

The asynchronous system yields doubly, it yields to its own userland scheduler/event loop and it's de-scheduled by the preemptive multitasking OS it runs on top of.

Re:Fast, Safe, and Complete(ish) Web Service in Rust by zzzcpan on Tuesday March 27, 2018 @05:08PM (#16692734)
Any process or thread can be descheduled by the OS on top of the stuff it does on its own.

Yielding is a thing from the multithreaded world with synchronous APIs. Asynchronous systems don't yield, they are programmed asynchronously. They have no yielding overhead and can never be slower than yielding threads.

If you are arguing for 1:1 kernel threading against M:N threading (coroutines, goroutines, green threads) that's fine, but multithreading implementations have absolutely nothing to do with asynchronous systems.

Re:Fast, Safe, and Complete(ish) Web Service in Rust by zbentley on Tuesday March 27, 2018 @06:40PM (#16693467)
It seems like the two of you disagree fundamentally on what "asynchronous" means in this context.

https://en.wikipedia.org/wiki/Asynchrony_(computer_programmi...

Re:Fast, Safe, and Complete(ish) Web Service in Rust by zzzcpan on Tuesday March 27, 2018 @09:35PM (#16694451)
I don't think we disagree on that, since he explicitly mentions event loops and essentially claims they are generally slower. Which is nonsense.
Re:Fast, Safe, and Complete(ish) Web Service in Rust by rictic on Tuesday March 27, 2018 @03:34PM (#16691977)
All of these examples are running on preemptive multithreaded operating systems, so implicitly yielding and getting scheduled is in the cards even if your process is managing its own concurrency with cooperative multithreading.
Re:Fast, Safe, and Complete(ish) Web Service in Rust by k__ on Tuesday March 27, 2018 @02:48PM (#16691570)
So where are the benefits coming from in these "rediscoveries"?
Re:Fast, Safe, and Complete(ish) Web Service in Rust by zzzcpan on Tuesday March 27, 2018 @02:56PM (#16691658)
Sometimes async is not real async, but an emulation, this is where "rediscoveries" come in I suppose.