read_piece_alert and streaming (continued from arvidn/libtorrent) #833
Replies: 4 comments 15 replies
-
@anacrolix I'm not sure though are you getting these GH notifications from @ mentions in your repo? |
Beta Was this translation helpful? Give feedback.
-
This is as implemented by the storage implementation in use. For example file-based storages don't have any caching, but there are some piece-based storage wrappers that allow you to evict pieces as wanted pretty easily. By caching I mean that the data can go away later.
Go in general, and the anacrolix/torrent Reader interface are blocking APIs and are implicitly asynchronous under the hood. That is to say that Go will handle things using asynchronous APIs in its runtime. async/await is just an explicit syntax allowing asynchronous implementations underneath.
I think this is the original post on function colouring. http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
If you return events to the user asynchronously, the state may change between issuing the event and having the chance to act on it. For example if a piece or file becomes available, it may be evicted before the user code can use it. It's just a complication that synchronous events avoid (and bring different problems instead). |
Beta Was this translation helpful? Give feedback.
-
@anacrolix to continue our conversation in this thread if I may, I replied to you a week ago, I don't know if you received my message below..
FWIW Roman Elizarov has this to say in that same article about the design decisions of Swift compared to Kotlin: "So, we mark asynchronous functions with suspend modifier in Kotlin and argue that it helps. Shouldn’t we apply the same argument to the call-sites of these functions and introduce some kind of await? Interestingly enough, if you read Async/await proposal for Swift, you find that its design is very similar to Kotlin Coroutines Design (it is direct, promise-free and uses continuations under the hood), but syntactically it follows C# tradition with async keyword to mark functions and await keyword on their call-sites, even though with promise-free design await can be made optional since compiler knows when asynchronous function is being invoked."
Well I'm generally wary of making types even stronger or do more work (though Go goes too far in the other direction) but yeah Kotlin seems to have struck a fine balance by eliding await. Regarding function coloring, type theorist Ted Kaminski (who also helped make the open source Kani Rust verifier for AWS, which additionally checks unsafe code) said this: "Exposing asynchrony in our programming model does create a distinction between two different kinds of functions. But that distinction always existed, it just wasn’t visible. It was just always handled on our behalf. For OS threading, that handling was blocking. For green threading, that handling is hoping that a true blocking case doesn’t sneak in somehow, because this is all handled behind the scenes. Promises and async/await make it explicit. They do so with very small runtimes, and a relatively minimal “function coloring” problem. (Especially minimal if you buy the argument the I/O should be more segmented off from the rest of a program.) It’s absolutely debatable whether making something explicit is better or not. One is not always universally superior. But when making it implicit means that we’re writing programs in a synchronous world-view that’s entirely at odds with how the world actually works, then I become skeptical that implicit is better. Maybe it’s better if our mental model for how our program works is more in line with how the world actually works." As I said, on the balance I would favor the marking of async functions explicitly. Note that Ted also touches on runtime overhead. There are to be sure tradeoffs with either approach, though I can't help but think the runtime overhead (with the stackfull coroutines) is concretely relevant with your own library as this issue keeps popping up: |
Beta Was this translation helpful? Give feedback.
-
@anacrolix to continue our conversation in this thread if I may, I replied to you a week ago, I don't know if you received my message below..
FWIW Roman Elizarov has this to say in that same article about the design decisions of Swift compared to Kotlin: "So, we mark asynchronous functions with suspend modifier in Kotlin and argue that it helps. Shouldn’t we apply the same argument to the call-sites of these functions and introduce some kind of await? Interestingly enough, if you read Async/await proposal for Swift, you find that its design is very similar to Kotlin Coroutines Design (it is direct, promise-free and uses continuations under the hood), but syntactically it follows C# tradition with async keyword to mark functions and await keyword on their call-sites, even though with promise-free design await can be made optional since compiler knows when asynchronous function is being invoked."
Well I'm generally wary of making types even stronger or do more work (though Go goes too far in the other direction) but yeah Kotlin seems to have struck a fine balance by eliding await. Regarding function coloring, type theorist Ted Kaminski (who also helped make the open source Kani Rust verifier for AWS, which additionally checks unsafe code) said this: "Exposing asynchrony in our programming model does create a distinction between two different kinds of functions. But that distinction always existed, it just wasn’t visible. It was just always handled on our behalf. For OS threading, that handling was blocking. For green threading, that handling is hoping that a true blocking case doesn’t sneak in somehow, because this is all handled behind the scenes. Promises and async/await make it explicit. They do so with very small runtimes, and a relatively minimal “function coloring” problem. (Especially minimal if you buy the argument the I/O should be more segmented off from the rest of a program.) It’s absolutely debatable whether making something explicit is better or not. One is not always universally superior. But when making it implicit means that we’re writing programs in a synchronous world-view that’s entirely at odds with how the world actually works, then I become skeptical that implicit is better. Maybe it’s better if our mental model for how our program works is more in line with how the world actually works." As I said, on the balance I would favor the marking of async functions explicitly. Note that Ted also touches on runtime overhead. There are to be sure tradeoffs with either approach, though I can't help but think the runtime overhead (with the stackfull coroutines) is concretely relevant with your own library as this issue keeps popping up: |
Beta Was this translation helpful? Give feedback.
-
All the alerts are asynchronous in libtorrent @anacrolix (not synchronous) The proposal has a read piece call that will notify (with an alert called
read_piece_alert
) when the specified piece is downloaded, and provides the piece data in a buffer. That's all.You talk about cache space, is this something your torrent library maintains and is configurable by the client? Or is this just a generic client side caching mechanism you're talking about that is not relevant to your library?
I'm not sure what function colouring is (attaching an "async" keyword?), though I thought Go concurrency and the async/await mechanism pioneered by C# are fundamentally using the same thing under the hood: coroutines (but one is stackfull and the other is stackless.)
Your view is as you admit opinionated, and that these are different axes of consideration .. Do you have a post or article in mind that would help explain this view to me so that I may learn more about it?
I don't doubt your implementation is efficient, but why is it programmed against using a blocking API, and not an async/nonblocking API?
You talk about evicting pieces, I guess your library maintains a cache of some sort that is user visible/configurable? Why?
Why do pieces necessarily need to be in a cache or main memory to be delivered to callers as part of a stream oriented Reader API? If they happen to be already downloaded and on disk or in an OS buffer (and not in the library maintained cache) can't they still be read and then delivered / stitched together with relevant pieces to be delivered to the caller?
Beta Was this translation helpful? Give feedback.
All reactions