book-exploring-async-basics
book-exploring-async-basics copied to clipboard
volunteer to translate the book into Chinese
Hi, I am a developer from China. I found the book useful when I tried to figure out what eventloop is. Actually I'm still at the beginning part of this book slowly. I volunteer to translate the book into Chinese. Here I am to ask for your permission, and possible help when I could not confirm the idea I got is totally what you want to express.
@Johnny4Fun That's cool.
Go ahead, just link to the original source in the start of the translated book please. I would really appreciate a link once you're done, so I can refer to the translation so Chinese readers can read your translation if they prefer.
If you have any questions just ask them here and I'll do my best to clarify/answer them.
@cfsamson Awesome.
I just forked the repo and have most finished chapter 1 and 2 yesterday. Here are the sentences behind from which I want to know the inner intent or which I want to ensure that I got your idea totally.
In Chapter11_concurrent_vs_parallel.md
Concurrency is about dealing with a lot of things at the same time.
at the same time means during a period
Parallelism is about doing a lot of things at the same time.
Here, at the same time is literally at the same point of time.
Concurrency is about working smarter. Parallelism is a way of throwing more resources at the problem.
Can you make the word smart more concrete? Or can I translatesmart into with smart strategies or effecient
When we talk about concurrency without providing any other context we are using you as a programmer and your code (your process) as the reference frame. If you start pondering about concurrency without keeping this in the back of your head it will get confusing very fast.
We tended to keep the assumption that using you as a programmer and your code (your process) as the reference frame in our mind unconsciously, which actually is what we should realize. So we should not make such implicit assumption, because this fixed assumption/precondition makes us get confused easily.
@cfsamson BTW, can I post the translated parts on 知乎(like chinese version Quora) then I can get some Chinese readers' review and advice. Absolutely, I'll put the original link of gitbook in every posts.
Concurrency is about dealing with a lot of things at the same time. at the same time means during a period Parallelism is about doing a lot of things at the same time. Here, at the same time is literally at the same point of time.
I agree that this is one way to put it. The important distinction is that "dealing with a lot of things" means you have tasks in "progress" at the same time don't necessarily perform work on them at the exact same time (i.e. in parallel).
In English you can say "I have a lot to deal with right now", that means you have many things to handle, but not that you're actually doing two things at the exact same time. You wouldn't say you have a lot to deal with if you're walking while talking on the phone (which is parallel since you're both moving from A to B and having a conversation about something unrelated).
Concurrency is about working smarter. Parallelism is a way of throwing more resources at the problem. Can you make the word smart more concrete? Or can I translatesmart into with smart strategies or effecient
I would say your translation is on point. "Smarter" means using your resources in a more optimal manner.
We tended to keep the assumption that using you as a programmer and your code (your process) as the reference frame in our mind unconsciously, which actually is what we should realize. So we should not make such implicit assumption, because this fixed assumption/precondition makes us get confused easily.
The translation seems a bit confusing to me. I actually go a bit more into detail here later in the book, but it's important to realize that when we talk about a "task", "resource", "blocking" and so on that we're in the context of the programmer and the code she/he writes. What we perceive as "blocking" might just be the operating system simply suspending your thread and switch to another task.
From the OS perspective it views our thread/process as one of many tasks it needs to handle so from that perspective we're not "blocking" any resource, it just goes on and schedules something else. It doesn't know about our sub-tasks like "handle a request" the same way we do, it views our thread as a task.
The meaning of "task", "resource" and "blocking" might change again when we view it from the context of the CPU and so on.
If we don't make a clear distinction about what context we're viewing things from it can get confusing pretty fast.
@cfsamson BTW, can I post the translated parts on 知乎(like chinese version Quora) then I can get some Chinese readers' review and advice. Absolutely, I'll put the original link of gitbook in every posts.
Sure, go ahead 👍
Thanks sooooo much for your patience!!!! BTW, I am wondering whether I need to @ you every time I have questions or not.
When we talk about concurrency without providing any other context we are using you as a programmer and your code (your process) as the reference frame. If you start pondering about concurrency without keeping this in the back of your head it will get confusing very fast.
I think I got the underlying idea now. But let's just talk about the paragraph above itself. Sorry for my poor! I tried to split the complex sentences into simple sentences.
- The default context is that we are using you as a programmer and your code/process as the reference frame.
- So later when we talk about concurrency without any other context, the default context is implicitly used.
- When you ponder about concurrency without the default context, you will get confused.
Especially about the sentence 3, is keeping this in the back of your head means forget or keep in mind? Sorry for my poor English again!
No problem. Yeah, I think you got it now. Sentence 3 means you need to remember this for the next chapters or more generally:
When you read an article or just sit and try to reason about concurrency in general the question you should always ask yourself is "what context are we using now"?
Btw, no, you don't need to use "@" every time since I get notified anyway, but if you don't get a response you can do it so you're 100 % sure it pops up in my feed.
I'm back here again!
Here are the parts got me confused in 2_async_history.md
Typically the programmer
yieldedcontrol to the OS.
So In Non-Preemptive multitasking it's programmer who decided when to handle the UI update tasks and run the background tasks. And after the program finished, the programmer need to yield control back to the OS. So I think there should be more words at the end of the sentence, like after the programmer finished the job..
Since you're not actually running two CPU's there will be some operations that need to wait for each other to finish.
Even though hypertheading can simulate 2 cores, there are some limits for certain operations that not allow one core shared by others at literally the same time. It's just simulation with some constrains.
So how synchronous is the code you write, really?
Is it equal to Is the code you write truly synchronous?
As a high-level overview, it's OK to model the CPU as operating in asynchronous manner, but lets for now just make a mental note that this is a model with some caveats that become especially important when talking about parallelism, synchronization primitives (like mutexes and atomics) and the security of computers and operating systems.
- In general, it's OK to model the CPU as operating in asynchronous manner.
- But we should be careful when talking about parallelism and so on, the model can be false.
- So be careful.
Hi.
So In Non-Preemptive multitasking it's programmer who decided when to handle the UI update tasks and run the background tasks. And after the program finished, the programmer need to yield control back to the OS. So I think there should be more words at the end of the sentence, like after the programmer finished the job.
This seems right. However, it's not only when the programmer is finished, the programmer needed to yield regularely to allow the OS to handle events like UI and background tasks. I don't know it the programmer needed to explicitly yield after the program was finished or not or if control was passed to the OS by default.
Even though hypertheading can simulate 2 cores, there are some limits for certain operations that not allow one core shared by others at literally the same time. It's just simulation with some constrains.
Yes, we're really getting into low level details here so there might be architectural differences. "A core" can internally consist of several parts, like the FPU and the ALU where the FPU can be thought of as a co-processor. These two co-processors can work in parallel for example. However, here are so many caveats here when it comes to memory access, instruction prefetching, out-of-order execution and so on that I think it's best to just accept that it's not going to be a 100% perfect description.
Is it equal to Is the code you write truly synchronous?
Yes
In general, it's OK to model the CPU as operating in asynchronous manner. But we should be careful when talking about parallelism and so on, the model can be false. So be careful.
Oh, it seems I accepted a PR that changed "synchonous" to "asynchonous" in that sentence. That should be "synchonous". I'll make sure to change that asap.
And yes, I think it's ok to think of the CPU as synchronous at a high level, as long as you know that it's not strictly true at the lowest levels, which is apparent when dealing with atomics and so on: https://cfsamsonbooks.gitbook.io/explaining-atomics-in-rust/
Here are the link of the collection in which in post the translation finished: 译:异步编程基础. You can use google to translate the article back to make sure I expressed what you want ( If you want).
In 3_0_the_operating_system.md
When programming it's often easy to forget how many moving pieces that need to cooperate when we care about efficiency.
What confused me is just the phrase moving pieces.
"Operating systems has been "faking" synchronous execution since the 90s."
The next question is about the word synchronous. Apparently it's a antonym of synchronous. However in my eyes its meaning is more like continuous or uninterrupted in this context. If I got the wrong point, could you plz show me some synonyms of the word.
What confused me is just the phrase moving pieces.
It means there are many independent pieces that need to cooperate tightly for a system to be efficient. Like an engine or a mechanical clock.
The next question is about the word synchronous. Apparently it's a antonym of synchronous. However in my eyes its meaning is more like continuous or uninterrupted in this context. If I got the wrong point, could you plz show me some synonyms of the word.
You're right (synchronous is an antonym of asynchronous). Yes, I think uninterrupted or continuous is good words to use if you want to explain in other words.
It means there are many independent pieces that need to cooperate tightly for a system to be efficient. Like an engine or a mechanical clock.
So what's the purpose of the sentence here? From the next seveal sentences, I know that the OS is the agent for us to request most hardwares we can not access to. But the first sentence
When programming it's often easy to forget how many moving pieces that need to cooperate when we care about efficiency.
looks weird and is not related to the topic of its section.
In file 3_1_communicating_with_the_os.md:
We also need to clobber the registers we write to so that we let the compiler know that we're modifying them and it can't rely on storing any values in these.
Does clobber here mean mark?
Every Linux installation comes with a version of
libcwhich a C-library for communicating with the operating system.
Is there a missing is after which?
The parameters don't need to have the same name but they must be in the right order
In the right order here actually means that the type of parameters should be same one-to-one? How about the return type?
fn write(fd: u32, buf: *const u8, count: usize) -> i32;
// | | |
ssize_t write(int fd, const void *buf, size_t count);
Usually, constants are defined in the C header files which we can't link to, so we need to search them up
so where can we search up the constants? the C header files like unistd.h or just google it.
So what's the purpose of the sentence here? From the next seveal sentences, I know that the OS is the agent for us to request most hardwares we can not access to. But the first sentence
You might be right that I can phrase that better but, in essence I mention some of the "moving pieces" below, the CPU, NIC, OS so I don't think it's that bad or out of place TBH.
We also need to clobber the registers we write to so that we let the compiler know that we're modifying them and it can't rely on storing any values in these.
It's about telling the compiler that it can't rely on these registers to store data since we modify them and overwrite/change what's there. Take a look at this paragraph.
Is there a missing is after which?
Yes, that's a spelling mistake. Thanks for catching it.
In the right order here actually means that the type of parameters should be same one-to-one? How about the return type?
Yes, that's right. The return type too, but it can only go one place so the thing I wanted to explain was that the naming of the parameters has no impact. You can't write "fd" as the second parameter and expect the compiler/linker to figure out that you want the file-descriptor there. It needs to be the first parameter but you can name it whatever you like.
So where can we search up the constants? the C header files like unistd.h or just google it.
C header files is the best place to get them. Google them is also an option, and you can also look at libraries like libc in rust and get them there.
The recommended way is to use the crate libc which has most of them for Rust, however I wanted to show it from the ground up in this book so that means searching header files and so on to get them.
Hello, there are my questions in 3_2_cross_platform_abstractions.md:
This is a recurring problem when we're curious about how 'this' works on three different platforms, but we need some basic understanding of how the different operating systems work under the covers.
So there are two questions:
- How does 'this' work on the three different platforms?
- What's the underlying difference on the three different platforms?
The two questions are co-dependent to each other, namely recurring. And I'm confused about what 'this' refers to?
This complexity ~~is~~ why the Rust community (other languages often has something similar) gathers around crates like libc which already have defined most methods and constants you need.
You mean, the Rust community encapsulates crates like libc for developers to hide the complexity of cross-platform.
BTW, I think there should be a missing is in front of why to make the sencente complete.
One hurdle is to get something working, which can prove to be quite a challenge.
what's the meaning of get something working, get some parts of the code working for certain platform?
Hello, there are my questions in 3_3_the_cpu_and_the_os.md:
We run programs on the CPU and we can do whatever we want if we know how to do it. Now, first of all, I wouldn't have thought this through, but unless you learn how this work from the bottom up, it's not easy to know for sure.
So we have already known that the programs run on the CPU from the previous chapters. So As long as we know how to drive the CPU, we can do everything, which is your previous understanding and leads to the answer NO. But Now, you have changed your answer into YES. And the readers need to learn how it works from the bottom up, then they could know why YES.
But can't we just change the page table in the CPU?
to be more concrete, that is changing the pointer pointing to the page table in the CPU, because the page table exists in memory, right?
This is a recurring problem when we're curious about how this works on three different platforms, but we need some basic understanding of how the different operating systems work under the covers.
So there are two questions: How does 'this' work on the three different platforms? What's the underlying difference on the three different platforms? The two questions are co-dependent to each other, namely recurring. And I'm confused about what 'this' refers to?
That is a bad paragraph on my part. I would just remove it from the book, it's awkwardly worded and doesn't add anything interesting. I'll try to go through some of the spelling mistakes and awkward wordings on my part here later and clean up based on your question. For now, I would just skip the paragraph.
You mean, the Rust community encapsulates crates like libc for developers to hide the complexity of cross-platform. BTW, I think there should be a missing is in front of why to make the sentence complete.
Yeah, the "is" is missing. Crates like libc doesn't really hide the complexity of cross platform development, but it makes it much easier. I refer to the previous paragraph where I mention all the structures you need to define on Windows, and how you need to read the documentation + header files to find all constants. All of this is encapsulated in libc so now you only need to read the docs to see how things work, you don't have to know how every piece of data is defined or the value of every constant.
what's the meaning of get something working, get some parts of the code working for certain platform?
Yes. The point I wanted to convey is that one thing is to get something working at all, but you're not done. You still need to know with a 100% certainty that it works correctly on all kinds of input and that can be a huge job in itself.
So we have already known that the programs run on the CPU from the previous chapters. So As long as we know how to drive the CPU, we can do everything, which is your previous understanding and leads to the answer NO. But Now, you have changed your answer into YES. And the readers need to learn how it works from the bottom up, then they could know why YES.
I'm not a 100 % sure I understand your question here, but I'm referring to myself some years back when I was just writing code and thought that if I used a low level language or assembly I could control the CPU and do whatever I wanted. This was of course not true. So here we go from the bottom up explaining how our CPU and OS works together preventing us from accessing memory, hardware etc directly for security (and stability) reasons.
I think it's important since we need to understand that we must cooperate closely with the OS to write efficient code. There is no way for us to, for example, talk directly with the network card even if we wanted to.
to be more concrete, that is changing the pointer pointing to the page table in the CPU, because the page table exists in memory, right?
Yes that's correct.
That is a bad paragraph on my part. I would just remove it from the book, it's awkwardly worded and doesn't add anything interesting. I'll try to go through some of the spelling mistakes and awkward wordings on my part here later and clean up based on your question. For now, I would just skip the paragraph.
From the perspective of a Chinese reader, I found sometimes it's hard to figure out words like it, which, this, that really refer to until you know the main idea. Not just for your book. And I think
as a reader or translator, I should just skip some parts not so important to get the main idea totally, then try to tackle the confusing part.
I'm not a 100 % sure I understand your question here, but I'm referring to myself some years back when I was just writing code and thought that if I used a low level language or assembly I could control the CPU and do whatever I wanted. This was of course not true. So here we go from the bottom up explaining how our CPU and OS works together preventing us from accessing memory, hardware etc directly for security (and stability) reasons.
Yes, that is what I got.
That's sooooooo hard for non-native English speakers to read professional books!!! Thanks for your patience again!
No problem, I understand that some nuances can get lost and cause confusion. Some parts could probably be written clearer and better on my part as well. I think you're right to skip the confusing parts and go back and tackle them a bit later.
@Johnny4Fun Just to inform you. I had to change from the asm! macro to the llvm_asm! macro (the syntax is the same) to keep the examples working. See this commit for the changes 0460862a4ff1ca949aeb28af70f242a706ca1f2b
The reason is that a new Rust specific syntax has been merged with the nightly compiler which means the example will stop working some time in the future, but they will run fine using the llvm_asm! macro. See:
https://github.com/rust-lang/rust/pull/69171
https://www.reddit.com/r/rust/comments/gn6yh1/new_asm_syntax_from_rfc_2850_has_been_merged/
Okay, Thanks. I'll modify that in translations
In 4_interrupts_firmware_io.md:
The next step is that we register our interest in
readevents on that socket.
It is the word interest that troubles me a lot in Chinese. Can I just convert the sentence into The next step is that we register lisening for read events on that socket.
It is the word interest that troubles me a lot in Chinese. Can I just convert the sentence into The next step is that we register lisening for read events on that socket.
Yeah, I can understand that the wording is a bit unusual but it's pretty common to use when working with events like this. Your translation sounds a bit strange to me, but it might make more sense in Chinese.
The word "interest" here is used like you use it when you say: "I want to register my interest in getting notified if the weather forecast changes".
You could probably just rephrase my sentence to: "The next step is to let the OS know that we want to get notified if there is any read events on that socket.". It would mean the same, however, the word "interest" is used a lot in the articles and the documentation of these API's so it might be worth explaining if there is no good translation.
In 5_strategies_for_handling_io.md:
Reasonably performant
Does that mean good performance or bad performance?
Abundant memory usage is less of a problem
So compared with using the OS threads, green threads malloc smaller memory for stacks so there is lower possibility for the process to be OOM killed.
Rust's Futures model a task as a [State Machine] where a suspension point represents a
state.
Can I just delete the word 'point', because I think suspension is just a state. However with the word point, I feel somehow weird.
Hi, I get one advice for you!
In 8_0_implementing_our_own_runtime.md:
I've added comments to the code so it's easier to remember and understand.
Now, I've added some comments here to explain what they're for and in the coming chapters we'll cover every one of them.
I think you could combine there two paragraphs together and place the combination above the code section like the first paragraph. Here are my thoughts as a reader:
- Rookies like me tend to have the passion to figure out everything when something new appears, then we start to google every word in the code section and easily ignore the following part of the article. So if informed that you'll cover the structure later in advance, we would be more patient and "relaxed" to read the following part even though I am not quite understand it.
Does that mean good performance or bad performance?
I means good performance.
So compared with using the OS threads, green threads malloc smaller memory for stacks so there is lower possibility for the process to be OOM killed.
Yes
Can I just delete the word 'point', because I think suspension is just a state. However with the word point, I feel somehow weird.
Hmm, I'm a bit unsure about this since "suspension point 1" and "suspension point 2" are two different states. Well, it's suspended in both cases but the data which needs to be kept across suspension points can change so it's not the "same" state, a bit simplified the states would look like this:
enum States {
Initial,
Suspended1(u64, u64, String), // <-- suspension point 1
Suspended2(String), // <-- suspension point 2
Completed,
}
I think you could combine there two paragraphs together and place the combination above the code section like the first paragraph. Here are my thoughts as a reader:
Rookies like me tend to have the passion to figure out everything when something new appears, then we start to google every word in the code section and easily ignore the following part of the article. So if informed that you'll cover the structure later in advance, we would be more patient and "relaxed" to read the following part even though I am not quite understand it.
This is a great suggestion. Thanks, I'll change that asap.