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

Make `a + b` `A * B` then, multiplication of two potentially huge matrices. Same argument still holds, but now it's blocking (still just performing addition, only an enormous number of times).



It's not blocking, it's doing actual work.

Blocking is the way used by the old programming paradigm to deal with asynchronous actions, and it works by behaving the same way as when the computer actually computes thing, so that's where the confusion comes from. but the two situations are conceptually very different: in one case, we are idle (but don't see it), in another case we're busy doing actual work. Maybe in case 2. we could optimize the algorithm so that we spend more time, but that's not sure, whereas in case 1. there's something obvious to do to speed things up: do something at the same time instead of waiting mindlessly. Having a function marked async gives you a pointer that you can actually run it concurrently to something else and expect speed up, whereas with blocking syscall there's no indication in the code that those two functions you're calling next to each other with not data dependency between them would gain a lot to be run concurrently by spawning two threads.

BTW, if you want something that's more akin to blocking, but at a lower level, it's when the CPU has to load data from RAM: it's really blocked doing nothing useful. Unfortunately that's not something you can make explicit in high-level languages (or at least, the design space hasn't been explored) so when these kinds of behavior matters to you, that's when you dive to assembly.


A "non-blocking function" always meant "this function will return before its work is done, and will finish that work in the background through threads/other processes/etc". All other functions are blocking by default, including that simple addition "bar" function above.


Your definition is at odds with (for instance) JavaScript's implementation of a non-blocking function though, as it will perform computation until the first await point before returning (unlike Rust future which are lazy, that is: do no work before they are awaited on).

As I said before, most of what you call a “blocking function” is actually a “no opinion function” but since in the idiosyncrasy of most programming languages blocking functions are being called like “no opinion” ones, you are mixing them up. But it's not a fundamental rule. You could imagine a language where blocking functions (which contains an underlying blocking syscall) are being called with the block keyword and where regular functions are just called like functions. There's no relation between regular functions and blocking functions except path dependency that led to this particular idiosyncrasy we live in, it is entirely contingent.


> Your definition is at odds with (for instance) JavaScript's implementation of a non-blocking function though, as it will perform computation until the first await point before returning

Yes, that's syntactic sugar for returning a promise. This pattern is something we've long called a non-blocking function in Javascript. The first part that's not in the promise is for setting it up.


If you define a non-blocking function to be what you decide is non-blocking, that's a bit of cheating don't you think? ;)

How about this function:

    async fn toto( input: u8) -> bool {
      if input % 2 == 0 {
        true
      } else{
        false
      }
    }
Is it a non-blocking one or not according to your criteria?


We were just taking Javascript and now you're back to Rust? That same function with that same keyword acts differently in the two languages.

My best guess is you're defining it (mostly?) by the syntax while I'm defining it by how the function acts. By what I'm talking about, that's a non-blocking function in Rust, but written the exact same way in Javascript it's a blocking function.


> We were just taking Javascript and now you're back to Rust? That same function with that same keyword acts differently in the two languages.

Yes, that's the point, and they in both case they are being called non-blocking functions, despite behaving differently.

> My best guess is you're defining it (mostly?) by the syntax while I'm defining it by how the function acts

I'm defining them how they are commonly being referred to, whereas you're using some arbitrary criteria that is not even consistent, as you'll see below.

> By what I'm talking about, that's a non-blocking function in Rust, but written the exact same way in JavaScript it's a blocking function.

Gotcha!

If we get back to your definition above

> A "non-blocking function" always meant "this function will return before its work is done, and will finish that work in the background through threads/other processes/etc".

Then it should be a “blocking function” because what this function returns is basically a private enum with two variants and a poll method to unwrap them. There's nothing running in the background ever.

In fact, in Rust an async function never runs anything in the background: all it does is returning a Future which is a passive state machine, there's no magic in there, and it's not very different from a closure or an Option actually (in fact, in this example, it's practically an the same as an Option). Then you can send this state machine to an executor that will do the actual work, polling it to completion. But this process doesn't necessarily happens in the background (you can even block_on the future to make that execution synchronous).

So in reality there are two kinds of functions, the ones that returns immediately (async and regular functions) and the ones that block the execution and will return later on (the “blocking” functions). And among the two kinds of functions that do not block, there's also two flavors: the ones that returns results that are immediately ready, and the ones that returns results that won't be ready before some time.


..you're referring to features of the future as if they're instead features of the function?


I don't think I understand what you're asking.


Blocking on the future isn't a feature of the function that you asked about, and in fact as a comparison to javascript if you expand the example to include an `await` on the returned promise (and include something that's actually async) it also blocks to wait for a result in the same thread. Those are features of the future/promise, not features of the function.


I'm still unsure of what you mean. Of course blocking on the future is a property of the function! The future/promise can exist everywhere, including in non-async functions. The key difference with async functions is that you can block the execution flow on await and only them can do that. Futures/promises cannot by themselves.

But calling await on a future doesn't necessarily mean it will in fact block the flow of execution, it can also return the value instantly (which means it doesn't fit your previous definition of non-blocking function), but it's still a special function that needs to be handled like any other non-blocking function (you can't just call it to get the result, you need to “unwrap” the future by calling await on it).

What I pointed out is that your definition of the split between non-blocking and blocking function is inconsistent and the reason why it is is because you fundamentally get the non-blocking/blocking difference backwards. And that's not your fault actually, the syntax used in pretty much every language leads to this confusion if you don't take a step back and think about it.




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

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

Search: