This is my first attempt of writing for the public, so please do not judge me too harshly. I am currently going through a chapter
of my life, that I can only label as "uncertain". I am waiting for visas in 2 countries (New Zealand and Denmark), the
processing times and the arrogance with which the immigration officials respond would turn any confident person into a depressed,
sorry individual. To deal with this, I decided to do something I planned for a long time, but never actually got time for.
Properly learn Rust Programming Language and the libraries in its ecosystem. In this blog post I would like to
document my journey, providing daily summaries and listing out commits. I do this so:
- People who also want to learn Rust can look at my example and try to do something similar. They would see that there is no
magic to it, and if you show up regularly and have genuine passion for the language you would be able to learn it.
- I can approach my learning with proper structure. I know that I need to write every day about it, so I have to learn
something new to do so.
- It would be easier to receive feedback from experienced Rustaceans, because all my work would be public.
- Possible future employers would see, that I actually know the stuff I claim I know.
I plan this to be a 2-3 month long project, and at the end of it I would love to have a couple of merged PRs into repositories
maintained by the rust-lang organisation.
Here is the list of resources in no particular order I identified as helpful:
Rust Projects: Established Open Source
| Project | Progress | Reason |
shuttle | 1 merged PR | Listened to one of the maintainers at TokioConf |
Rust Projects: Solo and with IRL Close Friends
Summary:
Just more syntax today.
Summary:
I shouldn't slow down.
Summary:
Continuing practicing the Rust Syntax. Nothing major. The "do something meaningful day is still in the future"
Rest Day
Summary:
I think I have an idea of what I want to do. Understand concurrency good enough, so I can build my own primitive and publish it on crates.io. It must reach
a 1000 downloads by the end of 2026.
- I wouldn't be able to write something like this on my own. But if now I am given a task to work with some data from different threads I would
be able to do so without creating undefined behaviour.
- Finished Reading Chapter 3.
- Work
- Stuff that happens in different threads can be matched in different ways. If we are interacting with the same variables from different threads,
that may create errors. To prevent that we can create happens-before relationships between different threads using "release-stores" and "acquire-loads".
- Practically this can help with Lazy Initialization.
Watching Stuff
- The Cost of Concurrency Coordination with Jon Gjengset
- If you have a lot of work use Mutexes, if you don't - don't. Cache miss would introduce a lot of overhead.
- The left-right data structure is useful when we have a lot of short readers and not a lot of writers.
- It is: Two copies of the data (l, r). Pointer points to the side all readers should read from. The other one is writer-owned.
- When writer is done, the pointer switches to the other side.
- Each reader has their own cache line. They just keep the counter of how many times they read the pointer. They do not need to talk to each other.
- Reads are Wait and Lock free.
- "Even the "lock-free" code can suffer from cache coherence".
- Always remember CSE 142 and the Amdahl's law
- Questions to ask yourself when you are choosing between
Mutex, RwLock and left-right:
- What is my read/write ratio?
- How long is my critical section?
- How many threads will content?
- Do I need linearizability?
Summary:
I don't really want to speak about today. I am more aware about the ownership model, I am getting more comfortable with iterators and
I know which method I should use when I work with Collections.
- Solved the TTL Cache Problem. I made the assumption that
we can go back in time, as the platform provided me with delta which is a signed integer. This means, that
I cannot just delete the data that we know have expired. Otherwise, the major chunk of the work could be
done by the
tick function and we would keep the data field as having the only information.
Summary:
I wouldn't call today productive. I spent a lot of time writing code myself, diving into the world of concurrency, but nothing major.
I did not generate anything significant on my own. And that is what is usually required at a workplace. I should focus more on that tomorrow.
Switch from a "reading day" to "applying the knowledge day". Also I identified a couple of typos in the rust by practice repo, and I
should edit them. At least in this way I can be useful to people. Also, throughout the whole day today I kept repeating the words of
YouTuber GothamChess about actually finishing the courses. Just saying you learn something is not
enough, you need to complete books/courses from start to finish. Yes, maybe the brute-force approach is not beautiful and elegant but it will yield a result.
I sound like one of those motivation-centered online gurus right now :)
- I am getting into more interesting topics where the rust really shines, like pattern matching.
- Doing this exercises makes me a fast thinker. I learn how to identify an error quickly, edit the file
in
nvim, save it, switch to the browser, run the snip, see the compilation error, return to nvim, repeat.
This trains my muscle memory and makes me a better terminal user.
- 8.1: Pattern Match - match, matches!, if let
- 8.2: Pattern Match - patterns
- 9: Methods and Associated functions
- I decided to make a new repo where I can execute each of the examples as:
cargo run --example ch<num-chapter>-ex<num-example>-<num-example>. Because just sharing gists for the
commented code, like I did yesterday is strange. I moved all the examples from Chapters 1 and Chapters 2 there.
Here is the commit
- Finished Reading Chapter 2.
- Work
- I am comfortable with
Atomics.
- I can spawn threads in many different ways and use closures correctly.
- I understand the idea behind
compare_exchange method.
- Started Reading Chapter 3.
- Work
- Happens-Before Relationship can be achieved between the threads.
- Compiler still has room for optimizations with Rust's memory model.
- Wrote my first bit of unsafe rust.
Mutexes just use the Release-Aquire ordering to establish happens-before relationships.
- This is the project I found yesterday on /rust subreddit. I like the concept. Each of the problems:
virtual file system, URL router, TTL cache can be its own project in separate repository.
But setting everything up is so time consuming. I would rather use an online platform with tests. Nobody will use a
rate limiter that I wrote, and I want (some day) for my GitHub to be a place where people go for code they can use.
(Doesn't connect well with a new repo I created in a section above though :| )
- Today I worked on the Sliding Window Rate Limiter. The problem was marked as easy, so it was the obvious one to start with.
My approach was simple, we have a number and we need to check in how many intervals it is already present. Intervals are sorted,
and can be defined by one number, as
windowMs is constant. If number of ocurences is above the specified threshold, return false,
otherwise add an interval corresponding to the input number to the Data Structure. BTreeMap in Rust
seemed like a right choice, as we want to be able to get a range of entries on-demand.
- You can see my implementation here.
- Fix the bad logic I wrote for deleting the currently playing song from fs, so that it is removed from the queue.
Summary:
I wouldn't call today productive. I spend a big part of the day setting up the blog itself, so I didn't have
a lot of time left for a proper learning session. I feel like I am stuck in some sort of a 'tutorial hell'. That
stuff I am going through over and over is extremely obvious to others. But I think it is necessary to go over basics until they click properly.
I add the key takeaways inside the commit descriptions.