#prog #go #article
How we found a bug in Go's arm64 compiler
TL;DR:для горутин с большим стеком (больше, чем может быть закодировано в литерале в одной инструкции на ARM) в эпилоге функций изменение sp, регистра, указывающего на верхушку стека, происходило через две операции ADD, обе из которых оперировали на sp непосредственно. Если переключение (preemption) между горутинами происходило между этими двумя операциями, любые операции, которые разворачивали стек — в частности, сборщик мусора — следовали вверх по стеку вызовов по частично обновлённому и потому невалидному значению из sp, и в результате предсказуемо крашились.
Может, ввести отдельный хештег для историй дебага? 🤔
How we found a bug in Go's arm64 compiler
TL;DR:
Может, ввести отдельный хештег для историй дебага? 🤔
The Cloudflare Blog
How we found a bug in Go's arm64 compiler
84 million requests a second means even rare bugs appear often. We'll reveal how we discovered a race condition in the Go arm64 compiler and got it fixed.
🤡7👍5❤1😱1🌚1
#prog #article
Cloudflare just got faster and more secure, powered by Rust
Про то, как в Cloudflare заменяют (пока что не довели до конца, но закончат к началу 2026 года) так называемый FL, центральный компонент своих сервисов. Заголовок несколько вводит в заблуждение: Rust определённо помогает, но большая часть хороших вещей из новой версии связана с архитектурой.
Одна из вещей, которая даёт преимущество новой версии — разделение на модули, каждый из которых сам по себе не занимается IO и явно перечисляет, что он принимает на вход и что возвращает. Это не только даёт возможность на уровне архитектуры явно видеть, как модули зависят друг от друга, но и позволило интегрировать модули в предыдущую версию FL, чтобы избежать параллельной поддержки двух версий одних и тех же функций во время перехода с одной версии на другую.
Отдельно хочу отметить, что часть про отсутствие IO язык с системой эффектов (даже такой примитивной, как в Haskell) мог бы предовтращать надёжно на уровне компилятора, а не соглашений, так что конкретно тут Rust не помогает.
Cloudflare just got faster and more secure, powered by Rust
Про то, как в Cloudflare заменяют (пока что не довели до конца, но закончат к началу 2026 года) так называемый FL, центральный компонент своих сервисов. Заголовок несколько вводит в заблуждение: Rust определённо помогает, но большая часть хороших вещей из новой версии связана с архитектурой.
Одна из вещей, которая даёт преимущество новой версии — разделение на модули, каждый из которых сам по себе не занимается IO и явно перечисляет, что он принимает на вход и что возвращает. Это не только даёт возможность на уровне архитектуры явно видеть, как модули зависят друг от друга, но и позволило интегрировать модули в предыдущую версию FL, чтобы избежать параллельной поддержки двух версий одних и тех же функций во время перехода с одной версии на другую.
Отдельно хочу отметить, что часть про отсутствие IO язык с системой эффектов (даже такой примитивной, как в Haskell) мог бы предовтращать надёжно на уровне компилятора, а не соглашений, так что конкретно тут Rust не помогает.
The Cloudflare Blog
Cloudflare just got faster and more secure, powered by Rust
We’ve replaced the original core system in Cloudflare with a new modular Rust-based proxy, replacing NGINX. It’s not only substantially faster for all our customers, it’s also more secure, and lets us ship new products quicker than ever before.
👍6🤡2🤔1
Блог*
конкретно тут Rust не помогает
This media is not supported in your browser
VIEW IN TELEGRAM
😁11❤🔥3🤡3💯3❤1👍1
#prog #article
Know your SCM_RIGHTS
TIL что в Linux (на самом деле UNIX) есть способ передавать файловые дескрипторы между процессами. И эти файловые дескрипторы могут быть в том числе TCP- и UDP-сокетами.
Know your SCM_RIGHTS
TIL что в Linux (на самом деле UNIX) есть способ передавать файловые дескрипторы между процессами. И эти файловые дескрипторы могут быть в том числе TCP- и UDP-сокетами.
The Cloudflare Blog
Know your SCM_RIGHTS
As TLS 1.3 was ratified earlier this year, I was recollecting how we got started with it here at Cloudflare. We made the decision to be early adopters of TLS 1.3 a little over two years ago. It was a very important decision, and we took it very seriously.
👍6😍3🤡2👌1
#prog #cpp #rust #article
Why we didn't rewrite our feed handler in Rust
Отдельно отмечается, что Rust в технологическом стеке в этой компании уже есть и успешно используется. Проблемы возникли с переписыванием конкретного компонента, который уже есть и написан на C++. Конкретно в тексте приведены три паттерна, которые валидны в C++ и не выразимы или выразимы неудобно на Rust.
Первое касается ограничений borrow checker-а. Вот какой пример приводят:
Простой и понятный код — но, к сожалению, выделяющий память в цикле. Логично было бы вынести аллокацию за цикл и очищать буфер в конце — но тогда компилятор не даёт скомпилировать код:
Второй паттерн — самоссылающиеся структуры, известная больная тема в Rust.
Третий паттерн — множество определений разных версий и унифицированный код для работы с ними (из-за необходимости поддержки разных версий схем обмена данных, насколько я понял). Пример из статьи на C++:
Унифицированный код для работы с обоими этими типами можно написать при помощи шаблонов:
Нетрудно видеть, как это обобщается на случай большего количества полей и различных версий. В Rust можно попробовать сделать нечто подобное, но это вырождается в бойлерплейт, облегчать который приходится макросами — иными словами, попытка повторить шаблоны из C++.
Why we didn't rewrite our feed handler in Rust
Отдельно отмечается, что Rust в технологическом стеке в этой компании уже есть и успешно используется. Проблемы возникли с переписыванием конкретного компонента, который уже есть и написан на C++. Конкретно в тексте приведены три паттерна, которые валидны в C++ и не выразимы или выразимы неудобно на Rust.
Первое касается ограничений borrow checker-а. Вот какой пример приводят:
fn process_source(sources: Vec<Source>) {
for source in sources {
let mut buffer: Vec<&[u8]> = Vec::new();
let data: Vec<u8> = source.fetch_data();
buffer.extend(data.split(splitter));
process_data(&buffer);
}
}
Простой и понятный код — но, к сожалению, выделяющий память в цикле. Логично было бы вынести аллокацию за цикл и очищать буфер в конце — но тогда компилятор не даёт скомпилировать код:
error[E0597]: `data` does not live long enough
--> src/lib.rs:32:23
|
31 | let data: Vec<u8> = source.fetch_data();
| ---- binding `data` declared here
32 | buffer.extend(data.split(splitter));
| ------ ^^^^ borrowed value does not live long enough
| |
| borrow later used here
33 | process_data(&buffer);
34 | }
| - `data` dropped here while still borrowed
Второй паттерн — самоссылающиеся структуры, известная больная тема в Rust.
Третий паттерн — множество определений разных версий и унифицированный код для работы с ними (из-за необходимости поддержки разных версий схем обмена данных, насколько я понял). Пример из статьи на C++:
struct RecV1 {
uint32_t x;
uint32_t y;
}
struct RecV2 {
uint32_t x;
uint32_t y;
uint32_t z;
}
Унифицированный код для работы с обоими этими типами можно написать при помощи шаблонов:
template <typename T>
T InitRec() {
T res;
res.x = 1;
res.y = 2;
if constexpr(std::is_same_v<T, RecV2>()) {
res.z = 3;
}
return res;
}
Нетрудно видеть, как это обобщается на случай большего количества полей и различных версий. В Rust можно попробовать сделать нечто подобное, но это вырождается в бойлерплейт, облегчать который приходится макросами — иными словами, попытка повторить шаблоны из C++.
👍10🤡6🔥1
Блог*
#prog #cpp #rust #article Why we didn't rewrite our feed handler in Rust Отдельно отмечается, что Rust в технологическом стеке в этой компании уже есть и успешно используется. Проблемы возникли с переписыванием конкретного компонента, который уже есть и…
Надо отметить, что первый пример с оптимизацией действительно не компилируется в лоб, но это не значит, что от аллокации в цикле нельзя избавиться. Именно, вот такой код с использованием bumpalo компилируется:
В этом коде арена, которая в реализации и выделяет память, конструируется один раз за пределами цикла и позволяет переиспользовать память, но версия вектора из bumpalo создаётся заново на каждой итерации и потому может позволить себе иметь время жизни, сравнимое с временами жизни переменной итерации. Вызывать при этом явно
fn process_source(sources: Vec<Source>) {
let b = bumpalo::Bump::new();
for source in sources {
let data = source.fetch_data();
let mut buffer = bumpalo::collections::Vec::new_in(&b);
buffer.extend(data.split(splitter);
process_data(&buffer);
}
}
В этом коде арена, которая в реализации и выделяет память, конструируется один раз за пределами цикла и позволяет переиспользовать память, но версия вектора из bumpalo создаётся заново на каждой итерации и потому может позволить себе иметь время жизни, сравнимое с временами жизни переменной итерации. Вызывать при этом явно
.clear()
за счёт RAII не требуется.docs.rs
bumpalo - Rust
`bumpalo`
🤔6🤡4🤮1
Блог*
Надо отметить, что первый пример с оптимизацией действительно не компилируется в лоб, но это не значит, что от аллокации в цикле нельзя избавиться. Именно, вот такой код с использованием bumpalo компилируется: fn process_source(sources: Vec<Source>) { …
Папищек подсказывает, что в std Rust предлагают добавить метод для работы с подобными случаями, и, более того, предложение ссылается на ту же статью
GitHub
Vec::recycle · Issue #674 · rust-lang/libs-team
Proposal Problem statement Re-using a Vec as buffer sometimes runs into lifetime issues. A recycle method that clears the Vec and essentially transmutes it into another Vec (using into_raw_parts &a...
😁9👍1🔥1🤡1🤷1
Почему "национализация" означает "переход в собственность государства", а не "превращение в страну"?
🤔4👍2🤡2😁1
#prog #rust #abnormalprogramming
fibonacci-numbers crate with self-recursive dependencies
fibonacci-numbers crate with self-recursive dependencies
I have created a crate called fibonacci-numbers. There are 187 different major versions of the crate, each exporting the Fibonacci number corresponding to that version.
<...>
Version 186 depends on version 184 and 185 and exports the largest Fibonacci number that fits in a u128:
pub const VALUE: u128 = fib184::VALUE + fib185::VALUE;
😁27🔥7🤡4🤯1
#prog #article
That boolean should probably be something else
Да, про сумм-типы там тоже упоминается.
That boolean should probably be something else
By storing a boolean as our data, we're coupling that data tightly to our application logic.
Instead, we should remain critical and ask what data the boolean depends on, and should we maybe store that instead?
Да, про сумм-типы там тоже упоминается.
🤡1
#prog #abnormalprogramming
spellscript
output: the power is amplified: 49
spellscript
esotoric [sic!] programming language that's read like a spellbook
begin the grimoire.
summon the power with essence of 7.
conjure ritual named amplify with value to return value multiplied by value.
enchant power with essence 0 of through ritual amplify with power.
inscribe whispers of "the power is amplified: " bound with power.
close the grimoire.
output: the power is amplified: 49
❤8🤡4🤯1