#prog #rust #performancetrap #article
Статья о том, как апгрейд до новой версии tokio привёл к тому, что сервер, обычно отвечающий меньше, чем за миллисекунду, начал отвечать ровно за 40 миллисекунд. Спойлер: как всегда в подобных случаях, баг образовался из-за взаимодействия нескольких механизмов, включая части из linux.
Статья о том, как апгрейд до новой версии tokio привёл к тому, что сервер, обычно отвечающий меньше, чем за миллисекунду, начал отвечать ровно за 40 миллисекунд. Спойлер: как всегда в подобных случаях, баг образовался из-за взаимодействия нескольких механизмов, включая части из linux.
Vorner’s random stuff
40 Ms Bug
40 millisecond bug
Блог*
#prog #rust #моё Как сравнить в Rust две строки, игнорируя регистр символов? Строго говоря, используя лишь стандартную библиотеку — никак, поскольку перевод из одного регистра в другой зависит от локали, но давайте пока проигнорируем эту деталь и притворимся…
Я говорил это ранее и скажу ещё раз: Вафель умница. Вскоре после того, как я выложил этот пост, он опубликовал вариант
starts_with_ignoring_case
с более простой реализацией.Telegram
Мне не нравится реальность
upd: можно даже проще и элегантнее:
fn starts_with_ignoring_case(s: &str, prefix: &str) -> bool {
let mut prefix = prefix.chars().flat_map(char::to_lowercase);
s.chars().flat_map(char::to_lowercase)
.zip(prefix.by_ref())
.all(|(a…
fn starts_with_ignoring_case(s: &str, prefix: &str) -> bool {
let mut prefix = prefix.chars().flat_map(char::to_lowercase);
s.chars().flat_map(char::to_lowercase)
.zip(prefix.by_ref())
.all(|(a…
#prog #rust #rustlib
Библиотека spirit — для снижения количества бойлерплейта при написании долгоживущих серверов. Логгирование, перечитывание конфигов при изменении, реагирование на сигналы, оборачивание в демоны — вот это вот всё.
Библиотека spirit — для снижения количества бойлерплейта при написании долгоживущих серверов. Логгирование, перечитывание конфигов при изменении, реагирование на сигналы, оборачивание в демоны — вот это вот всё.
#prog #rust #rustlib #amazingopensource
Заметки о библиотеке для использования постфиксных макросов, с изложением мотивации для её создания, истории вопроса и немного о реализации.
Заметки о библиотеке для использования постфиксных макросов, с изложением мотивации для её создания, истории вопроса и немного о реализации.
use postfix_macros::{postfix_macros, unwrap_or};
fn main() {
postfix_macros! {
let urls = ["https://rust-lang.org", "https://github.com"];
for url in urls.iter() {
let mut url_splitter = url.splitn(2, ':');
let scheme = url_splitter.next().unwrap();
let _remainder = url_splitter.next().unwrap_or! {
println!("Ignoring URL: No scheme found");
continue;
};
println!("scheme is {}", scheme);
}
}
}
Мои знакомые — особенно те, кто сами ведут свой канал в Телеграм — спрашивают, как мне удаётся постить качественный контент каждый день.
Ответ очень прост: я выкладываю некачественный контент.
Ответ очень прост: я выкладываю некачественный контент.
#psy
О том, как правильно извиняться. Написано в контексте брака, но, на мой взгляд, вполне применимо и в более общих ситуациях.
TL;DR: Извиняетесь, но не заставляйте просить прощения
В этот раз ссылка на приватный канал в Telegram, так что вот вам сначала инвайт, а потом уже и ссылка на сам пост.
О том, как правильно извиняться. Написано в контексте брака, но, на мой взгляд, вполне применимо и в более общих ситуациях.
TL;DR: Извиняетесь, но не заставляйте просить прощения
В этот раз ссылка на приватный канал в Telegram, так что вот вам сначала инвайт, а потом уже и ссылка на сам пост.
Forwarded from <илья as Человек> (ilya sheprut)
блять, опять я всё своё свободное время потратил в телегу и нихера не напрогал. Надо удалять её нафиг
#prog #cpp
twitter.com/AffectiveCpp — лучший твиттер-аккаунт о C++. Полезен даже профессионалам, а новичкам так и вовсе практически обязателен.
twitter.com/AffectiveCpp — лучший твиттер-аккаунт о C++. Полезен даже профессионалам, а новичкам так и вовсе практически обязателен.
X (formerly Twitter)
Affective C++ (@AffectiveCpp) on X
The authoritative guide for High Quality C++!
(Warning: These are all jokes.)
(Warning: These are all jokes.)
Блог*
#prog #rust #article На этот раз — статья про концепцию разномерности типа в Rust. github.com/pretzelhammer/rust-blog/blob/master/posts/sizedness-in-rust.md
#prog #rust #compiler #article
Восхитительная длинная статья от Крендель-молота про написание компилятора brainfuck под x86_64, ARM64, WASM и LLVM IR.
github.com/pretzelhammer/rust-blog/blob/master/posts/too-many-brainfuck-compilers.md
Восхитительная длинная статья от Крендель-молота про написание компилятора brainfuck под x86_64, ARM64, WASM и LLVM IR.
github.com/pretzelhammer/rust-blog/blob/master/posts/too-many-brainfuck-compilers.md
GitHub
rust-blog/posts/too-many-brainfuck-compilers.md at master · pretzelhammer/rust-blog
Educational blog posts for Rust beginners. Contribute to pretzelhammer/rust-blog development by creating an account on GitHub.
Блог*
#prog #rust tip: спецификатор фрагмента vis в макросах сопоставляется с описанием видимости определения, в том числе и пустым. К примеру, следующий код компилируется: macro_rules! accept_with_vis { ($vis:vis struct $name:ident;) => {} } accept_with_vis!{struct…
...Но не когда нужно сопоставиться только с спецификатором видимости (thanks @sajitar, который и заполнил issue). Вот этот код не компилируется:
macro_rules! accept_just_vis {
($vis:vis) => {}
}
accept_just_vis!{}
GitHub
macro_rules! and empty :vis metavariables · Issue #71422 · rust-lang/rust
Hi. I founds some bugs, did a research, and created a repository with reproducible examples, README, and instructions. Here is the content of README, and the whole repo is attached as zip archive. ...
#prog #rust #моё
Как многие из вас знают (а если не знаете — узнаете сейчас), в Rust нельзя перемещать (move) поля из значения типа, имеющего нетривиальную реализацию Drop. В частности, значение типа, реализующего
Пусть это выглядит примерно так:
Как многие из вас знают (а если не знаете — узнаете сейчас), в Rust нельзя перемещать (move) поля из значения типа, имеющего нетривиальную реализацию Drop. В частности, значение типа, реализующего
Drop
, нельзя деструктурировать. Однако надо отметить, что если тип поля реализует Copy
, то к этому полю можно обратиться, в том числе и пре деструктуризации, при этом значение этого поля скопируется. Проиллюстрирую только что сказанное:struct NonCopy;
struct Dropping<T>(T, NonCopy);
impl<T> Drop for Dropping<T> {
fn drop(&mut self) {
println!("dropped");
}
}
fn main() {
// ⬇️ если раскомментировать эту строку, то программа не скомпилируется с E0509
// let Dropping(_non_copy, _) = Dropping(NonCopy, NonCopy);
// А вот это — компилируется и печатает "dropped".
// Обратите внимание, паттерн `_`
*не* перемещает значение.
let Dropping(_x, _) = Dropping(0_u32, NonCopy);
}
Где это может выстрелить? При написании биндингов к сишным либам. Одна их техник обеспечения инкапсуляции в C — это определение структуры в заголовочном файле без определения её полей. Это позволяет получить доступ к полям структуры только там, где дано её определение, а внешний код может обращаться к ней лишь по указателю. И указатель — это Copy
-тип, да.Пусть это выглядит примерно так:
extern "C" {
// extern types ещё не стабилизированы, так что
// в реальной библиотеке, скорее всего, будут использовать *mut std::ffi::c_void
type Some_C_Struct;Что произойдёт, если мы попытаемся деструктурировать
fn c_lib_release_resources(arg: *mut Some_C_Struct);
}
struct Handle(*mut Some_C_Struct);
impl Drop for Handle {
fn drop(&mut self) {
unsafe { c_lib_release_resources(self.0) }
}
}
Handle
? Скажем, нам зачем-то потребовалась реализация метода leak
:impl Handle {Что можно с этим сделать? Использовать ManuallyDrop. Этот тип предотвращает вызов деструктора (а также деструктуризацию, поскольку у него приватные поля), но при этом не предотвращает доступ к полям значения внутри (через Deref). Возникает вопрос, почему не использовать std::mem::forget? В принципе, в документации подробно расписано, но если коротко, то
fn leak(self) -> *mut Some_C_Struct {
// Здесь мы разбираем значение, но так как указатель — Copy-тип,
// имя ptr привязывается к копии значения, перемещения не происходит.
let Handle(ptr) = self; // <-- после этой точки с запятой кончается время жизни self, и вызывается деструктор
// Ура, у нас на руках невалидный указатель!
ptr
}
}
std::mem::forget
значительно сложнее корректно использовать.doc.rust-lang.org
ManuallyDrop in std::mem - Rust
A wrapper to inhibit compiler from automatically calling `T`’s destructor. This wrapper is 0-cost.
Прошу прощения, в предыдущем опросе один диапазон возрастов просто не был представлен
Сколько вам лет?
(диапазон с включающей нижней и исключающей верхней границами)
(диапазон с включающей нижней и исключающей верхней границами)
Final Results
1%
0..10
7%
10..18
41%
18..25
25%
25..30
13%
30..35
7%
35..40
2%
40..45
1%
45..50
1%
50..60
1%
60..∞