From 6f9537524fe32138fe2b9b2933fb8b59e0aee696 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Fri, 9 Aug 2024 09:50:42 +0200 Subject: [PATCH] Fix some typos --- posts/chat-server.md | 4 ++-- posts/too-many-brainfuck-compilers.md | 2 +- posts/tour-of-rusts-standard-library-traits.md | 2 +- .../zh-hans/tour-of-rusts-standard-library-traits.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/posts/chat-server.md b/posts/chat-server.md index 9a83a10..28dfaa7 100644 --- a/posts/chat-server.md +++ b/posts/chat-server.md @@ -1104,7 +1104,7 @@ And to quote the `RwLock` docs from the `parking_lot` crate: I guess we just have to be really careful 🤷 -**3\)** Aquire locks in the same order everywhere +**3\)** Acquire locks in the same order everywhere If we need to acquire multiple locks to safely perform some operation, we need to always acquire those locks in the same order, otherwise deadlocks can trivially occur, like here: @@ -1728,7 +1728,7 @@ We have a lot of short strings. We can have thousands of users and hundreds of r As you may remember, when we `send` something to a broadcast channel every call to `recv` clones that data. That means if a user sends a `String` message that is five paragraphs long in a room with 1000 other users we're going to have to clone that message 1000 times which means doing 1000 heap allocations. We know that after a message is sent it's immutable, so we don't need to send a `String`, we can convert the `String` to an `Arc` instead and send that, because cloning an `Arc` is very cheap since all it does is increment an atomic counter. -#### Miscellanous micro optimizations +#### Miscellaneous micro optimizations After combing through the code I found a couple places where we were carelessly allocating unnecessary `Vec`s and `String`s, mostly for the `/rooms` and `/users` commands, and made them both only allocate a single `String` when generating a response. diff --git a/posts/too-many-brainfuck-compilers.md b/posts/too-many-brainfuck-compilers.md index 553da92..072dbe4 100644 --- a/posts/too-many-brainfuck-compilers.md +++ b/posts/too-many-brainfuck-compilers.md @@ -2202,7 +2202,7 @@ System calls are expensive, even without including the cost of switching from us I learned a lot and still far less than I thought I would. Remember that laundry list of fancy terms I mentioned back in the intro of this article? Yeah well, I still don't know what half of that stuff is. -While doing the research and programming for this project I finally learned what _auto-vectorization_, _inlining_, _endianess_, _system calls_, _LLVM_, _SIMD_, and _ABI_ are. I kinda get what _linking_ is on a very basic level but I still get lost whenever I read anything about _linking_ because it seems like the linker does a whole bunch of really crazy complicated code manipulations other than just playing connect-the-dots with some global symbols, so I don't feel like I "fully get" what a linker actually does. I get what _custom allocators_ are in concept but I don't get why, for example, Allocator X is more performant than Allocator Y for certain workloads. This project never forced me to figure out how heap allocations work in assembly so it makes sense that allocators are still a mystery to me. I know that _TLS_ stands for Thread Local Storage and people love talking about it but I don't know why. I know _padding_ is a thing that exists purely to serve _alignment_ but I have no clue why _alignment_ is so important. Apparently if the data in your program is _aligned_ everything is faster and if it's _unaligned_ it's either slow or completely unusable. But why? What is it with all this magical _alignment_ stuff? +While doing the research and programming for this project I finally learned what _auto-vectorization_, _inlining_, _endianness_, _system calls_, _LLVM_, _SIMD_, and _ABI_ are. I kinda get what _linking_ is on a very basic level but I still get lost whenever I read anything about _linking_ because it seems like the linker does a whole bunch of really crazy complicated code manipulations other than just playing connect-the-dots with some global symbols, so I don't feel like I "fully get" what a linker actually does. I get what _custom allocators_ are in concept but I don't get why, for example, Allocator X is more performant than Allocator Y for certain workloads. This project never forced me to figure out how heap allocations work in assembly so it makes sense that allocators are still a mystery to me. I know that _TLS_ stands for Thread Local Storage and people love talking about it but I don't know why. I know _padding_ is a thing that exists purely to serve _alignment_ but I have no clue why _alignment_ is so important. Apparently if the data in your program is _aligned_ everything is faster and if it's _unaligned_ it's either slow or completely unusable. But why? What is it with all this magical _alignment_ stuff? I was very surprised by how much easier it was to write the x86_64 and aarch64 compilers compared to the WebAssembly and LLVM IR compilers. I think this mostly has to do with the fact that brainfuck is a super simple language that maps very cleanly to low-level assembly instructions and if I was writing compilers for a higher-level language it'd be easier to map higher-level constructs to WebAssembly and LLVM IR than x86_64 and aarch64 but I've never tried to do this so I can't say 100% for sure. diff --git a/posts/tour-of-rusts-standard-library-traits.md b/posts/tour-of-rusts-standard-library-traits.md index 32ad8b2..ce18208 100644 --- a/posts/tour-of-rusts-standard-library-traits.md +++ b/posts/tour-of-rusts-standard-library-traits.md @@ -2773,7 +2773,7 @@ fn main() { `Fn` refines `FnMut` in the sense that `FnMut` requires mutable references and can be called multiple times, but `Fn` only requires immutable references and can be called multiple times. `Fn` can be used anywhere `FnMut` can be used, which includes anywhere `FnOnce` can be used. -If a closure doesn't capture anything from its environment it's technically not a closure, but just an anonymously declared inline function, and can be casted to, used, and passed around as a regular function pointer, i.e. `fn`. Function pointers can be used anywhere `Fn` can be used, which includes anwhere `FnMut` and `FnOnce` can be used. +If a closure doesn't capture anything from its environment it's technically not a closure, but just an anonymously declared inline function, and can be casted to, used, and passed around as a regular function pointer, i.e. `fn`. Function pointers can be used anywhere `Fn` can be used, which includes anywhere `FnMut` and `FnOnce` can be used. ```rust fn add_one(x: i32) -> i32 { diff --git a/posts/translations/zh-hans/tour-of-rusts-standard-library-traits.md b/posts/translations/zh-hans/tour-of-rusts-standard-library-traits.md index 35b3f76..aa5daaf 100644 --- a/posts/translations/zh-hans/tour-of-rusts-standard-library-traits.md +++ b/posts/translations/zh-hans/tour-of-rusts-standard-library-traits.md @@ -3257,7 +3257,7 @@ fn main() { `Fn` 改良了 `FnMut` ,尽管它们都可以多次调用,但是 `FnMut` 需要参数的可变引用,而 `Fn` 仅需要参数的不可变引用。`Fn` 可以在所有 `FnMut` 和 `FnOnce` 可用的地方使用。 -> If a closure doesn't capture anything from its environment it's technically not a closure, but just an anonymously declared inline function, and can be casted to, used, and passed around as a regular function pointer, i.e. `fn`. Function pointers can be used anywhere `Fn` can be used, which includes anwhere `FnMut` and `FnOnce` can be used. +> If a closure doesn't capture anything from its environment it's technically not a closure, but just an anonymously declared inline function, and can be casted to, used, and passed around as a regular function pointer, i.e. `fn`. Function pointers can be used anywhere `Fn` can be used, which includes anywhere `FnMut` and `FnOnce` can be used. 如果一个闭包不从环境中捕获任何的值,那么从技术上讲它就不是闭包,而仅仅只是一个内联的匿名函数。并且它可以被转换为、用于或传递为一个常规函数指针,即 `fn`。函数指针可以用于任何 `Fn` ,`FnMut` ,`FnOnce` 可用的地方。