Small wordle project I made!
So I just started learning rust, and am just about to get to tests, but to consolidate everything that I have learnt so far, I decided to write a wordle clone! It includes colored text for each letter, accurate letter position guides (Green if correct, yellow if its in the word, with correct number of letters although there may be an issue with guessing something with letter pattern xxllx when the word has the pattern xxxlx (replace x with anything) as it checks in order, and would wrap the u8 I use round. There are of course solutions, but I can't think of one), both lowercse an upper case support, validation of it being in the alphabet and 5 letters long!
```rust
use std::{collections::HashMap, io};
use colored::*;
struct Guess {
word: String,
guess_info: ([char;5],HashMap<char,u8>)
}
impl Guess{
fn new() -> Guess{
let mut input = loop{
let mut input= String::new();
io::stdin().read_line(&mut input).expect("FAILED TO READ LINE!");
input = String::from(input.trim());
println!("{}",input);
if ! input.chars().all(char::is_alphabetic){
println!("Please only use letters in the english alphabet!");
continue;
}
if input.len() != 5{
println!("Please only use words of length 5!");
continue;
}
break input;
};
input = input.to_uppercase();
let guess_info = get_word_info(&input);
Guess { word: input, guess_info}
}
fn compare(&self, word:&str) -> [i32; 5]{
let word_info = get_word_info(&word);
let mut result = [0,0,0,0,0];
let mut word_char_count = word_info.1.clone();
if word_info.0 == self.guess_info.0{
result = [2,2,2,2,2];
}
else {
for i in 0..5{
let remaining_ref = word_char_count.get(&self.guess_info.0[i]);
let mut remaining: u8;
match remaining_ref{
Some(_t) => {
remaining = *remaining_ref.unwrap() as u8;
if remaining > 0{
if word_info.0[i] == self.guess_info.0[i]{
result[i] = 2;
} else{ result[i] = 1;}
remaining -= 1;
word_char_count.insert(self.guess_info.0[i], remaining);
} else{ result[i] = 0; }
},
None => {
result[i] = 0;
}
}
}
}
result
}
fn display(&self, result: [i32; 5]){
let mut display = ["".red(),"".red(),"".red(),"".red(),"".red()];
for i in 0..5{
let letter: &str = &self.word[i..i+1];
match result[i]{
2 => {display[i] = letter.green()},
1 => {display[i] = letter.yellow()},
_ => {display[i] = letter.red()}
}
}
println!("{}{}{}{}{}", display[0], display[1], display[2], display[3], display[4])
}
}
fn main() {
// init
const WORDS: [&str; 7] = ["HELLO","WORKS","TESTS","ADIEU","AUDIO","CRANE","PLANE"];
let word = WORDS[rand::random_range(0..WORDS.len())];
println!("----------WORDLE-----------");
println!("-----Terminal Edition------");
let mut win = false;
for _ in 0..6{
let guess = Guess::new();
let result = guess.compare(word);
guess.display(result);
if result == [2,2,2,2,2,]{
win = true;
break;
}
}
println!("---------GAME OVER---------");
if win{
println!("{}","You Win!".bright_cyan());
} else{
println!("{}","You Lose :(".red());
println!("The Word Was: {}",word.yellow())
}
So I just started learning rust, and am just about to get to tests, but to consolidate everything that I have learnt so far, I decided to write a wordle clone! It includes colored text for each letter, accurate letter position guides (Green if correct, yellow if its in the word, with correct number of letters although there may be an issue with guessing something with letter pattern xxllx when the word has the pattern xxxlx (replace x with anything) as it checks in order, and would wrap the u8 I use round. There are of course solutions, but I can't think of one), both lowercse an upper case support, validation of it being in the alphabet and 5 letters long!
```rust
use std::{collections::HashMap, io};
use colored::*;
struct Guess {
word: String,
guess_info: ([char;5],HashMap<char,u8>)
}
impl Guess{
fn new() -> Guess{
let mut input = loop{
let mut input= String::new();
io::stdin().read_line(&mut input).expect("FAILED TO READ LINE!");
input = String::from(input.trim());
println!("{}",input);
if ! input.chars().all(char::is_alphabetic){
println!("Please only use letters in the english alphabet!");
continue;
}
if input.len() != 5{
println!("Please only use words of length 5!");
continue;
}
break input;
};
input = input.to_uppercase();
let guess_info = get_word_info(&input);
Guess { word: input, guess_info}
}
fn compare(&self, word:&str) -> [i32; 5]{
let word_info = get_word_info(&word);
let mut result = [0,0,0,0,0];
let mut word_char_count = word_info.1.clone();
if word_info.0 == self.guess_info.0{
result = [2,2,2,2,2];
}
else {
for i in 0..5{
let remaining_ref = word_char_count.get(&self.guess_info.0[i]);
let mut remaining: u8;
match remaining_ref{
Some(_t) => {
remaining = *remaining_ref.unwrap() as u8;
if remaining > 0{
if word_info.0[i] == self.guess_info.0[i]{
result[i] = 2;
} else{ result[i] = 1;}
remaining -= 1;
word_char_count.insert(self.guess_info.0[i], remaining);
} else{ result[i] = 0; }
},
None => {
result[i] = 0;
}
}
}
}
result
}
fn display(&self, result: [i32; 5]){
let mut display = ["".red(),"".red(),"".red(),"".red(),"".red()];
for i in 0..5{
let letter: &str = &self.word[i..i+1];
match result[i]{
2 => {display[i] = letter.green()},
1 => {display[i] = letter.yellow()},
_ => {display[i] = letter.red()}
}
}
println!("{}{}{}{}{}", display[0], display[1], display[2], display[3], display[4])
}
}
fn main() {
// init
const WORDS: [&str; 7] = ["HELLO","WORKS","TESTS","ADIEU","AUDIO","CRANE","PLANE"];
let word = WORDS[rand::random_range(0..WORDS.len())];
println!("----------WORDLE-----------");
println!("-----Terminal Edition------");
let mut win = false;
for _ in 0..6{
let guess = Guess::new();
let result = guess.compare(word);
guess.display(result);
if result == [2,2,2,2,2,]{
win = true;
break;
}
}
println!("---------GAME OVER---------");
if win{
println!("{}","You Win!".bright_cyan());
} else{
println!("{}","You Lose :(".red());
println!("The Word Was: {}",word.yellow())
}
println!("----------------------------")
}
fn get_word_info(word:&str) -> ([char;5], HashMap<char,u8>){
let mut chars = [' ',' ',' ',' ',' '];
let mut i = 0;
let mut chars_count: HashMap<char, u8> = HashMap::new();
for chara in word.chars(){
chars[i] = chara;
let char_count = chars_count.entry(chara).or_insert(0);
*char_count += 1;
i += 1;
}
(chars, chars_count)
}
```
This is the file and I am very happy with it for a first project with minimal docs usage (I used them to double check hashmaps, and I used SO for checking if its alphabetical). Any way I could improve (other than fixing that one issue, which for now I might just use i8, and just deal with the fact that players might think that there is an extra of a letter)
EDIT: switching to i8 does not change anything, IDK why I thought it would
https://redd.it/1pwsq9n
@r_rust
}
fn get_word_info(word:&str) -> ([char;5], HashMap<char,u8>){
let mut chars = [' ',' ',' ',' ',' '];
let mut i = 0;
let mut chars_count: HashMap<char, u8> = HashMap::new();
for chara in word.chars(){
chars[i] = chara;
let char_count = chars_count.entry(chara).or_insert(0);
*char_count += 1;
i += 1;
}
(chars, chars_count)
}
```
This is the file and I am very happy with it for a first project with minimal docs usage (I used them to double check hashmaps, and I used SO for checking if its alphabetical). Any way I could improve (other than fixing that one issue, which for now I might just use i8, and just deal with the fact that players might think that there is an extra of a letter)
EDIT: switching to i8 does not change anything, IDK why I thought it would
https://redd.it/1pwsq9n
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
[P] NOMA: a Rust-built compiler where backprop is generated at compile time (LLVM IR), exploring “systems-first” ML
https://github.com/pierridotite/Noma
https://redd.it/1pwwx26
@r_rust
https://github.com/pierridotite/Noma
https://redd.it/1pwwx26
@r_rust
GitHub
GitHub - pierridotite/Noma: A systems programming language with native differentiation for bare-metal AGI.
A systems programming language with native differentiation for bare-metal AGI. - pierridotite/Noma
Built my first Rust project offline Markdown renderer for security documentation
I'm a developer who's been wanting to try Rust for ages. Finally got some time off this winter and decided to dive in.
**My learning approach:**
* Rustlings (got halfway through)
* Youtube tutorials and Rust Docs
* Building an actual tool – [Markdown Scribe](https://github.com/DhanushNehru/markdown-scribe)
I've always been a self learner
**Why I built this:**
In cybersec, I'm constantly writing documentation – vulnerability reports, penetration test findings, security advisories. I wanted a fast, offline-first Markdown tool that I could trust wouldn't leak my drafts to some cloud service. Something that runs locally, renders fast, and doesn't need 47 dependencies or an internet connection.
**What I loved about Rust:**
The biggest thing? **How easy it is to express intent in code.** Coming from Javanoscript and Python in the security world, Rust's type system and error handling forced me to think about edge cases I'd normally gloss over.
The strict error modeling taught me concepts I thought I already knew. For example, the distinction between `OsStr` and `str` – something that matters when you're dealing with file paths in security tools where encoding issues can be attack vectors.
**Zero-cost abstractions** are incredible. I built complex features without worrying about performance penalties. The compiler has your back.
**Developer tooling** is top-tier. Cargo makes dependency management painless, which is refreshing when you're used to dealing with security-critical libraries where supply chain attacks are a real concern.
Project is MIT licensed and open for contributions: [Markdown Scribe](https://github.com/DhanushNehru/markdown-scribe)
🌟 Star the repo - your support means a lot!
https://redd.it/1pwzjbk
@r_rust
I'm a developer who's been wanting to try Rust for ages. Finally got some time off this winter and decided to dive in.
**My learning approach:**
* Rustlings (got halfway through)
* Youtube tutorials and Rust Docs
* Building an actual tool – [Markdown Scribe](https://github.com/DhanushNehru/markdown-scribe)
I've always been a self learner
**Why I built this:**
In cybersec, I'm constantly writing documentation – vulnerability reports, penetration test findings, security advisories. I wanted a fast, offline-first Markdown tool that I could trust wouldn't leak my drafts to some cloud service. Something that runs locally, renders fast, and doesn't need 47 dependencies or an internet connection.
**What I loved about Rust:**
The biggest thing? **How easy it is to express intent in code.** Coming from Javanoscript and Python in the security world, Rust's type system and error handling forced me to think about edge cases I'd normally gloss over.
The strict error modeling taught me concepts I thought I already knew. For example, the distinction between `OsStr` and `str` – something that matters when you're dealing with file paths in security tools where encoding issues can be attack vectors.
**Zero-cost abstractions** are incredible. I built complex features without worrying about performance penalties. The compiler has your back.
**Developer tooling** is top-tier. Cargo makes dependency management painless, which is refreshing when you're used to dealing with security-critical libraries where supply chain attacks are a real concern.
Project is MIT licensed and open for contributions: [Markdown Scribe](https://github.com/DhanushNehru/markdown-scribe)
🌟 Star the repo - your support means a lot!
https://redd.it/1pwzjbk
@r_rust
GitHub
GitHub - DhanushNehru/markdown-scribe: A fast and extensible Markdown renderer and editor built in Rust, designed for client-side…
A fast and extensible Markdown renderer and editor built in Rust, designed for client-side use with no dependencies on servers or networks. - DhanushNehru/markdown-scribe
Why is calling my asm function from Rust slower than calling it from C?
https://ohadravid.github.io/posts/2025-12-rav1d-faster-asm/
https://redd.it/1pwzti4
@r_rust
https://ohadravid.github.io/posts/2025-12-rav1d-faster-asm/
https://redd.it/1pwzti4
@r_rust
ohadravid.github.io
Why is calling my asm function from Rust slower than calling it from C?
This is a follow-up to making the rav1d video decoder 1% faster, where we compared profiler snapshots of rav1d (the Rust implementation) and dav1d (the C …
Is Rust the future?
This is like 5th or 6th language I am learning, and I have to say I absolutely love it. It feels like the most complete, very well designed programming language. I love Rust, it is an absolute joy to write code.
However, coding is my side quest, my specialty is within cyber security mostly, and I don't really know much about current state and future. Would you say that Rust has a good future? Worth to learn fully?
https://redd.it/1px246m
@r_rust
This is like 5th or 6th language I am learning, and I have to say I absolutely love it. It feels like the most complete, very well designed programming language. I love Rust, it is an absolute joy to write code.
However, coding is my side quest, my specialty is within cyber security mostly, and I don't really know much about current state and future. Would you say that Rust has a good future? Worth to learn fully?
https://redd.it/1px246m
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
influxdb-stream: A streaming client for InfluxDB 2.x - feedback welcome!
Hey r/rust!
I built a small crate called influxdb-stream. This is my first time publishing to crates.io, so any feedback would be appreciated.
Problem: Existing InfluxDB clients load entire query results into memory. When dealing with millions of rows (e.g., data migrations), this causes OOM issues.
Solution: This crate streams records one at a time with O(1) memory usage.
---
\- GitHub: https://github.com/almightychang/influxdb-stream
\- crates.io: https://crates.io/crates/influxdb-stream
---
Would love to hear any suggestions on API design, error handling, or anything else I could improve. Thanks!
https://redd.it/1px186u
@r_rust
Hey r/rust!
I built a small crate called influxdb-stream. This is my first time publishing to crates.io, so any feedback would be appreciated.
Problem: Existing InfluxDB clients load entire query results into memory. When dealing with millions of rows (e.g., data migrations), this causes OOM issues.
Solution: This crate streams records one at a time with O(1) memory usage.
---
\- GitHub: https://github.com/almightychang/influxdb-stream
\- crates.io: https://crates.io/crates/influxdb-stream
---
Would love to hear any suggestions on API design, error handling, or anything else I could improve. Thanks!
https://redd.it/1px186u
@r_rust
crates.io
crates.io: Rust Package Registry
Why won't this match statement compile?
The match statement has every possible combination of the bool match guard for 0 but still expects a 0 in one of the match arms.
See this example here
updated with correct rust playground
https://redd.it/1px4sds
@r_rust
The match statement has every possible combination of the bool match guard for 0 but still expects a 0 in one of the match arms.
See this example here
updated with correct rust playground
https://redd.it/1px4sds
@r_rust
play.rust-lang.org
Rust Playground
A browser interface to the Rust compiler to experiment with the language
upcoming Gust - a Rust based package manager that's up to 265x faster than swiftPM
https://preview.redd.it/qx3lkstgxs9g1.png?width=1800&format=png&auto=webp&s=90014391688272621d06e1ceef73c89d8fa636f5
Gust is a rapid, lightweight, open-source, Swift package manager, written in Rust.
It is upto 265x faster than SwiftPM and 10-12x faster than flutter's pub.
Gust uses a linking algorithm that ensures there is never more than 1 instance of the same version of a library on your machine, just like pnpm saving gigabytes of space in the long run.
Why would you be interested in Gust?
1. Massive Disk Space Savings
2. Rapid Package Installations
3. Lower CPU, RAM Usage
4. Significantly Lower Bandwidth Usage
5. Large Cost Savings
When will Gust be released?
I've been working hard to add new features and make Gust robust. Right now, Gust is in a very early stage so it is not ready for use, however, the key mechanisms that make it faster and more efficient have already been put in place and I have used it to rapidly make iOS, and watchOs apps with Claude Code and released them on the app store
The best part? Gust is open source https://github.com/quantbagel/gust! If you would like to support Gust development or find the project interesting, a ⭐ would be hugely appreciated!
https://redd.it/1px76j4
@r_rust
https://preview.redd.it/qx3lkstgxs9g1.png?width=1800&format=png&auto=webp&s=90014391688272621d06e1ceef73c89d8fa636f5
Gust is a rapid, lightweight, open-source, Swift package manager, written in Rust.
It is upto 265x faster than SwiftPM and 10-12x faster than flutter's pub.
Gust uses a linking algorithm that ensures there is never more than 1 instance of the same version of a library on your machine, just like pnpm saving gigabytes of space in the long run.
Why would you be interested in Gust?
1. Massive Disk Space Savings
2. Rapid Package Installations
3. Lower CPU, RAM Usage
4. Significantly Lower Bandwidth Usage
5. Large Cost Savings
When will Gust be released?
I've been working hard to add new features and make Gust robust. Right now, Gust is in a very early stage so it is not ready for use, however, the key mechanisms that make it faster and more efficient have already been put in place and I have used it to rapidly make iOS, and watchOs apps with Claude Code and released them on the app store
The best part? Gust is open source https://github.com/quantbagel/gust! If you would like to support Gust development or find the project interesting, a ⭐ would be hugely appreciated!
https://redd.it/1px76j4
@r_rust
What are some exciting features that will be stabilized in future rust versions?
https://redd.it/1px9ol3
@r_rust
https://redd.it/1px9ol3
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
I wrote a Linux Tor firewall in Rust – feedback on structure welcome
https://github.com/ghaziwali/Hulios
https://redd.it/1px6mfa
@r_rust
https://github.com/ghaziwali/Hulios
https://redd.it/1px6mfa
@r_rust
GitHub
GitHub - ghaziwali/Hulios: A Rust-based transparent Tor proxy that routes all system traffic through the Tor network enhanced security…
A Rust-based transparent Tor proxy that routes all system traffic through the Tor network enhanced security, proper DNS isolation, and modern Linux compatibility. - ghaziwali/Hulios
Least technically capable Factorio player writes a FUSE filesystem in Rust for floppy disks and beats the game with it
https://www.youtube.com/watch?v=cTPBGZcTRqo&t=438
https://redd.it/1pxhffo
@r_rust
https://www.youtube.com/watch?v=cTPBGZcTRqo&t=438
https://redd.it/1pxhffo
@r_rust
YouTube
I Beat Factorio on Save Icons.
Solving a problem that nobody has.
Fluster Github repo:
https://github.com/DocJade/fluster_rs
Consider supporting me on Ko-fi!
https://ko-fi.com/docjade
Join the discord! http://discord.docjade.com/
Have a video idea? Let me know! https://forms.gle/u…
Fluster Github repo:
https://github.com/DocJade/fluster_rs
Consider supporting me on Ko-fi!
https://ko-fi.com/docjade
Join the discord! http://discord.docjade.com/
Have a video idea? Let me know! https://forms.gle/u…
This media is not supported in your browser
VIEW IN TELEGRAM
[Media] Looking for feedback on seekr, a GTK4 search launcher I wrote in Rust
https://redd.it/1pxmwrb
@r_rust
https://redd.it/1pxmwrb
@r_rust
How stable do you think the WASM ecosystem is going to be?
Say WASM develops into what people hope:
\- people could use Rust and other languages and frameworks instead of Javanoscript, HTTP and CSS
\-people could make C, C++ and Rust programs run in the browser.
How stable do you think this ecosystem is going to be, in terms of updates to the WASM stack, and in terms of dependencies breaking?
I'm aware WASM is already functional, so perhaps the current state can inform us on my question to a certain degree.
https://redd.it/1pxoqpn
@r_rust
Say WASM develops into what people hope:
\- people could use Rust and other languages and frameworks instead of Javanoscript, HTTP and CSS
\-people could make C, C++ and Rust programs run in the browser.
How stable do you think this ecosystem is going to be, in terms of updates to the WASM stack, and in terms of dependencies breaking?
I'm aware WASM is already functional, so perhaps the current state can inform us on my question to a certain degree.
https://redd.it/1pxoqpn
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
Rust & GPUI(zed) Based Markdown Editor
First post here, I have been working on a markdown editor, which is simple and efficient(I hope) and is open souce. I have made some progress and would love some feedback if anyone is willing to give some of their valuable time.
Aster is a Markdown editor built in Rust on top of GPUI, the GPU-accelerated UI framework from the Zed team.
https://github.com/kumarUjjawal/aster
https://redd.it/1pxmorp
@r_rust
First post here, I have been working on a markdown editor, which is simple and efficient(I hope) and is open souce. I have made some progress and would love some feedback if anyone is willing to give some of their valuable time.
Aster is a Markdown editor built in Rust on top of GPUI, the GPU-accelerated UI framework from the Zed team.
https://github.com/kumarUjjawal/aster
https://redd.it/1pxmorp
@r_rust
Utoipa vs Aide (for axum OpenAPI generation)
Hi all,
I wanted to hear from people with experience with both what their thoughts were.
My main motivation for using Utoipa is because i was under the impression that it was the default.
I am now building the documentation for my routes and was wondering whether i would be better served using Aide as the api documentation just happens.
I’m still in early development and will be introducing breaking changes so i would like to minimise the effort i spend rewriting docs and making sure i haven’t missed anything.
I have a few testing customers who wanted early access at a discount and so i figured having the docs automatically update properly on new routes or changed routes would be nice.
Thoughts?
https://redd.it/1pxq5q4
@r_rust
Hi all,
I wanted to hear from people with experience with both what their thoughts were.
My main motivation for using Utoipa is because i was under the impression that it was the default.
I am now building the documentation for my routes and was wondering whether i would be better served using Aide as the api documentation just happens.
I’m still in early development and will be introducing breaking changes so i would like to minimise the effort i spend rewriting docs and making sure i haven’t missed anything.
I have a few testing customers who wanted early access at a discount and so i figured having the docs automatically update properly on new routes or changed routes would be nice.
Thoughts?
https://redd.it/1pxq5q4
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
Try-rs v0.1.23 released! (A fast Rust CLI for temporary workspaces (now with Windows support)
Processing gif l06skiqq2v9g1...
Hello r/rust! 👋
I’d like to share a series of releases for try-rs, a Rust-based command-line tool designed to manage temporary workspaces and experiments in an organized and predictable way.
Instead of scattering random folders across your filesystem, try-rs automatically organizes them and provides an object-oriented user interface to create, navigate, search, and safely delete them.
🔗 GitHub: https://github.com/tassiovirginio/try-rs
🔗 Crates.io: https://crates.io/crates/try-rs
🔗 Aur: https://aur.archlinux.org/packages/try-rs-bin
# 🆕 What’s new (v0.1.18 → v0.1.23)
- First native Windows build (
- try-rs is now truly cross-platform
- GitHub Actions workflow added to build Windows artifacts
- New
- Improved entry loading and parsing logic
- README updated to clarify directory naming behavior
- Creation timestamp added to entries
- Directory naming logic refactored
- Date prefixes removed from generated/cloned folders
- Clearer documentation and updated GIFs
-
- First external contribution 🎉
https://redd.it/1pxszm9
@r_rust
Processing gif l06skiqq2v9g1...
Hello r/rust! 👋
I’d like to share a series of releases for try-rs, a Rust-based command-line tool designed to manage temporary workspaces and experiments in an organized and predictable way.
Instead of scattering random folders across your filesystem, try-rs automatically organizes them and provides an object-oriented user interface to create, navigate, search, and safely delete them.
🔗 GitHub: https://github.com/tassiovirginio/try-rs
🔗 Crates.io: https://crates.io/crates/try-rs
🔗 Aur: https://aur.archlinux.org/packages/try-rs-bin
# 🆕 What’s new (v0.1.18 → v0.1.23)
- First native Windows build (
.exe) published - try-rs is now truly cross-platform
- GitHub Actions workflow added to build Windows artifacts
- New
is_mise and is_cargo fields in TryEntry - Improved entry loading and parsing logic
- README updated to clarify directory naming behavior
- Creation timestamp added to entries
- Directory naming logic refactored
- Date prefixes removed from generated/cloned folders
- Clearer documentation and updated GIFs
-
TRY_PATH and TRY_CONFIG environment variables can now override default values - First external contribution 🎉
https://redd.it/1pxszm9
@r_rust
GitHub
GitHub - tassiovirginio/try-rs: A blazing fast, Rust-based workspace manager for your temporary experiments.
A blazing fast, Rust-based workspace manager for your temporary experiments. - tassiovirginio/try-rs
Why futures don't implement the typestate pattern?
Calling the
I'm implementing a socket library, and I'm tempted to use the typestate pattern (
So why is it so? Are there any unintended side effects with the typestate pattern? Should I use it anyway in my libraries?
https://redd.it/1pxv07q
@r_rust
Calling the
poll method on a Future in the Poll::Ready state is UB. Why the std library doesn't use the typestate pattern to avoid this issue? In theory it should not make a big performance difference: correctness is validated by the compiler, memory footprint should be the same and the check at runtime should be very cheap thanks to the branch predictor.I'm implementing a socket library, and I'm tempted to use the typestate pattern (
Socket<State> with possible states being Uninitialized, Open, Connecting, Receiving and Closed), but the fact that the std library doesn't use this pattern makes me dubious.So why is it so? Are there any unintended side effects with the typestate pattern? Should I use it anyway in my libraries?
https://redd.it/1pxv07q
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
Worlds fastest git status on windows - part 2 - ntdll, more speed, and reinventing the wheel
Hey everyone!
Last week I posted about writing the [fastest git status in the world](https://www.reddit.com/r/rust/comments/1prkzqg/writing_the_fastest_implementation_of_git_status/). (on windows!) There, we statused the **Linux repo in 137ms.** However the code wasn't what I would like it to be, and I had additional questions, so here is me sharing that adventure, and getting some additional nice speedups along the way.
Follow me traveller, into a world of windows apis, cache abuse, and accidentally reinventing the wheel.
Repo with source is at the bottom!
# Funny things with windows libraries
So previously, I used the windows api for file system stuff: `FindFirstFileExW` and `FindNextFileW` To recap - if you iterate per directory in windows, you go 20-50 times faster than if you do it per file, like you do in linux.
However, we have multiple windows apis! Lets try some out!
I had the impression that I could better nail down the cost of the actual directory walking, so I wrote some functions which do that and nothing else, to get a better base time. I should have sat down and done this earlier perhaps, but it was exciting to go into unknown holes of performance on windows, so the first git status I made was wild and unprincipled. This is still wild and unprincipled, but hopefully a little less so.
Lets see what we have:
|Library / Method|Time (ms)|Notes|
|:-|:-|:-|
|Git2 Status|555.70|Cold start - \~300ms if you run again|
|Win32 - directories|25.39|Same API as last time|
|ntdll - directories|20.59|Same as above but using NT|
Previously I got **46ms** for the walk, so this is definitely an improvement!
I don't really like using the NTDLL because you may wonder: how do I use this super fast api? Its easy! just call this:
let status = unsafe {
NtQueryDirectoryFile(
self.0, // FileHandle
ptr::null_mut(), // Event
None, // ApcRoutine
ptr::null_mut(), // ApcContext
&mut io_status, // IoStatusBlock
buffer.as_mut_ptr() as *mut c_void, // FileInformation
(buffer.len() * 8) as u32, // Length
FILE_DIRECTORY_INFORMATION, // FileInformationClass
0, // ReturnSingleEntry
ptr::null_mut(), // FileName
if restart_scan { 1 } else { 0 }, // RestartScan
)
};
See what I mean?
One thing I did is run the benchmarks in a different order. In my experience, there is a bunch of caching going on behind the scenes, and so you want to see how that behaves.
`[dirwalk_win32] walk=77.7819ms | threads=24 | dirs=5994 | files=90332`
Look at that, we're suddenly up to almost 80 milliseconds! What is happening? We know it's some kind of caching, but why is it like this? Running it multiple times in a row is also strange:
[dirwalk_win32] walk=77.8767ms | threads=24 | dirs=5994 | files=90332
[dirwalk_win32] walk=62.6251ms | threads=24 | dirs=5994 | files=90332
[dirwalk_win32] walk=41.3444ms | threads=24 | dirs=5994 | files=90332
[dirwalk_win32] walk=30.9595ms | threads=24 | dirs=5994 | files=90332
But there is more! It looks like the high-level API for this actually has a name cache, which is the cause of the slowness, but also it's per process. Which means that every time you want to run this in a new process, you get hit with the cache miss every time.
How did I get the 25ms time with it? Well it turns out that I was running it after the git2 status check, and, somehow, that maxes out its speed. Even though repeated calls to itself don't.
I'm not sure why it behaves like this, but regardless we see that it's really inconsistent.
By comparison, the NTDLL version is remarkably consistent. It takes a hit the first time the OS hasn't loaded the files
Hey everyone!
Last week I posted about writing the [fastest git status in the world](https://www.reddit.com/r/rust/comments/1prkzqg/writing_the_fastest_implementation_of_git_status/). (on windows!) There, we statused the **Linux repo in 137ms.** However the code wasn't what I would like it to be, and I had additional questions, so here is me sharing that adventure, and getting some additional nice speedups along the way.
Follow me traveller, into a world of windows apis, cache abuse, and accidentally reinventing the wheel.
Repo with source is at the bottom!
# Funny things with windows libraries
So previously, I used the windows api for file system stuff: `FindFirstFileExW` and `FindNextFileW` To recap - if you iterate per directory in windows, you go 20-50 times faster than if you do it per file, like you do in linux.
However, we have multiple windows apis! Lets try some out!
I had the impression that I could better nail down the cost of the actual directory walking, so I wrote some functions which do that and nothing else, to get a better base time. I should have sat down and done this earlier perhaps, but it was exciting to go into unknown holes of performance on windows, so the first git status I made was wild and unprincipled. This is still wild and unprincipled, but hopefully a little less so.
Lets see what we have:
|Library / Method|Time (ms)|Notes|
|:-|:-|:-|
|Git2 Status|555.70|Cold start - \~300ms if you run again|
|Win32 - directories|25.39|Same API as last time|
|ntdll - directories|20.59|Same as above but using NT|
Previously I got **46ms** for the walk, so this is definitely an improvement!
I don't really like using the NTDLL because you may wonder: how do I use this super fast api? Its easy! just call this:
let status = unsafe {
NtQueryDirectoryFile(
self.0, // FileHandle
ptr::null_mut(), // Event
None, // ApcRoutine
ptr::null_mut(), // ApcContext
&mut io_status, // IoStatusBlock
buffer.as_mut_ptr() as *mut c_void, // FileInformation
(buffer.len() * 8) as u32, // Length
FILE_DIRECTORY_INFORMATION, // FileInformationClass
0, // ReturnSingleEntry
ptr::null_mut(), // FileName
if restart_scan { 1 } else { 0 }, // RestartScan
)
};
See what I mean?
One thing I did is run the benchmarks in a different order. In my experience, there is a bunch of caching going on behind the scenes, and so you want to see how that behaves.
`[dirwalk_win32] walk=77.7819ms | threads=24 | dirs=5994 | files=90332`
Look at that, we're suddenly up to almost 80 milliseconds! What is happening? We know it's some kind of caching, but why is it like this? Running it multiple times in a row is also strange:
[dirwalk_win32] walk=77.8767ms | threads=24 | dirs=5994 | files=90332
[dirwalk_win32] walk=62.6251ms | threads=24 | dirs=5994 | files=90332
[dirwalk_win32] walk=41.3444ms | threads=24 | dirs=5994 | files=90332
[dirwalk_win32] walk=30.9595ms | threads=24 | dirs=5994 | files=90332
But there is more! It looks like the high-level API for this actually has a name cache, which is the cause of the slowness, but also it's per process. Which means that every time you want to run this in a new process, you get hit with the cache miss every time.
How did I get the 25ms time with it? Well it turns out that I was running it after the git2 status check, and, somehow, that maxes out its speed. Even though repeated calls to itself don't.
I'm not sure why it behaves like this, but regardless we see that it's really inconsistent.
By comparison, the NTDLL version is remarkably consistent. It takes a hit the first time the OS hasn't loaded the files
Reddit
From the rust community on Reddit
Explore this post and more from the rust community