1.93K subscribers
3.56K photos
136 videos
15 files
3.78K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
#prog #article

There is no memory safety without thread safety

Memory safety is all the rage these days. But what does the term even mean? <...> Typically, people use this term to refer to languages that make sure that there are no use-after-free or out-of-bounds memory accesses in the program. This is then often seen as distinct from other notions of safety such as thread safety, which refers to programs that do not have certain kinds of concurrency bugs. However, in this post I will argue that this distinction isn’t all that useful, and that the actual property we want our programs to have is absence of Undefined Behavior.
👍10🤔3
#prog #rust #article

What's "new" in Miri (and also, there's a Miri paper!)

It is time for another “what is happening in Miri” post. In fact this is way overdue, with the previous update being from more than 3 years ago <...>
5
#prog #article

On 'function coloring'

Exposing asynchrony in our programming model does create a distinction between two different kinds of functions. But that distinction always existed, it just wasn’t visible. It was just always handled on our behalf.
👍51🤔1
#prog #article

How uv got so fast

uv is fast because of what it doesn’t do, not because of what language it’s written in. The standards work of PEP 518, 517, 621, and 658 made fast package management possible. Dropping eggs, pip.conf, and permissive parsing made it achievable. Rust makes it a bit faster still.

pip could implement parallel downloads, global caching, and metadata-only resolution tomorrow. It doesn’t, largely because backwards compatibility with fifteen years of edge cases takes precedence. But it means pip will always be slower than a tool that starts fresh with modern assumptions.
👍17
#prog #rust #article

OnceMap: Rust Pattern for Running Concurrent Work Exactly Once

When multiple tasks need the same resource, how do you ensure the work happens exactly once? uv’s solution is OnceMap - a lightweight concurrent memoization primitive that powers deduplication across the resolver and installer.
Не смотря на то, что код приведён для Rust, подход, судя по всему, можно адаптировать и под другие языки.
🤔32
#prog #article

snuffle / salsa / chacha

Небольшой текст про анатомию ChaCha20, крутое свойство этого шифра (которым обладают далеко не все поточные шифры) и про то, как это шифр был рождён из-за, внезапно, #politota соображений.
👍8
#prog #article

GSoC 2025: Usability Improvements for the Undefined Behavior Sanitizer

clang поддерживает несколько санитайзеров, в том числе UBSan для отловки неопределённого поведения (с оговорками). Запускать их при этом можно в двух разных режимах. Первый — с добавлением рантайма, который при детектировании UB перед завершением работы программы печатает, что конкретно пошло не так. Второй вариант — без рантайма, в котором при детектировании UB просто исполняется trap-инструкция процессора.

Второй вариант больше годится для случаев, когда важны оверхед на производительность и размер компилированного кода (в embedded, например). Проблема в том, что UX у такого решения ужасный: получай аварийное завершение программы, а что именно пошло не так — гадай сам. И даже дебаггер в этих случаях не особо помогает, потому что он максимум укажет на инструкцию рядом с trap и на соответствующую строку исходного кода, но не более.

Anthony Tran задался целью исправить этот недостаток. С этой целью он модифицировал кодогенерацию так, чтобы к trap-инструкции прицеплялась отладочная информация, в которую уже включалось человекочитаемое сообщение об ошибке. Этот подход хорош тем, что сразу же подхватывается существующими отладчиками. Разумеется, дополнительная отладочная информация требует места, но оверхед на размер кода на практике пренебрежимо мал.

Не обошлось без костылей из-за ограниченности DWARF:

To accomplish this, we needed to find a place to “stuff” the string in the DWARF DIE tree. Using a
DW_TAG_subprogram was deemed the most straightforward and space-efficient location. This means we create a synthetic DISubprogram which is not a real function in the compiled program; it exists only in the debug info as a container.
<...>
When a trap is hit in the debugger, the debugger retrieves this string from the debug info and shows it as the reason for trapping.
👍8
#prog #rust #article

What does it take to ship Rust in safety-critical?

Статья про очень конкретные препятствия к использованию Rust в safety-critical системах.

Это именно препятствия, а не блоки — в этих областях Rust уже используется в проде.
🤔2
#prog #rust #article

Офигенно!

Rust's standard library on the GPU

GPU code can now use Rust's standard library. We share the implementation approach and what this unlocks for GPU programming.


This works because of our custom hostcall framework. A hostcall is analogous to a syscall. A hostcall is a structured request from GPU code to the host CPU to perform something it cannot execute itself. You can think of it like a remote procedure call from the GPU to the host to achieve syscall-like functionality.

To end users, Rust's std APIs appear unchanged and act as one would expect.
12👍7
#prog #c #article

You (probably) don’t need to learn C

I’m all for learning C if it will be useful for the job at hand, but you can write lots of great software without knowing C. [выделение моё]

A few people repeated the idea that C teaches you how code “really” executes. But C is an abstract model of a computer, and modern CPUs do all kinds of things that C doesn’t show you or explain. Pipelining, cache misses, branch prediction, speculative execution, multiple cores, even virtual memory are all completely invisible to C programs.

C is an abstraction of how a computer works, and chip makers work hard to implement that abstraction, but they do it on top of much more complicated machinery.
5👍3💩3😁2
#math #article

Hobby’s algorithm for aesthetic Bézier splines

Разновидность сплайнов для "гладкой" интерполяции точек, которая быстро работает (пропорционально числу точек) и зачастую даёт эстетически приятные результаты. Из недостатков: передвижение опорных точек меняет форму всей кривой, и малое передвижение опорной точки может привести к радикальной смене формы кривой в районе этой точки.

В самом начале есть интерактивная демонстрация.
🤔2
#prog #article

A Tale Of Four Fuzzers

Восхитительная статья от matklad-а, в частности, хорошая демонстрация того, как писать фаззеры.

Some time ago we overhauled TigerBeetle’s routing algorithm to better handle varying network topologies in a cluster. That turned out to be an interesting case study of practical generative testing (or fuzzing) for non-trivial, real-world code. We ended up adding not one, not even two, but four very different new fuzzers to the system! Let’s talk about why just one fuzzer is not enough.
👍6
#prog #article

BTW PVS-Studio развивают версию своего анализатора для #go, и хотя для широкой публики анализатор ещё не доступен (в апреле будет бета-версия), он уже находит множество ошибок, которые не находит go vet. Все найденные ошибки при этом на Go не завязаны, так что, возможно, в будущем анализатор станет ещё полезнее конкретно для Go.
👍8
#prog #rust #article

В стандартной библиотеке Rust есть несколько ассоциативных контейнеров: HashMap, HashSet, BTreeMap и BTreeSet. Часто на практике в качестве ключей в них хранятся строки — String. Требовать от пользователя для поиска значение типа String неудобно и чревато проблемами в производительности. Потому у этих структур данных есть API, позволяющие использовать для поиска ключи других, "похожие" на те, что хранятся в контейнере.

Возьмём в качестве примера HashMap::get:

fn get<Q>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,


Как видно из кода, тип для поиска (Q) не обязан совпадать с типом хранимых ключей (K), но на K есть ограничение K: Borrow<Q>. Трейт Borrow выглядит таким образом:

trait Borrow<Borrowed>
where
Borrowed: ?Sized,
{
fn borrow(&self) -> &Borrowed;
}


В процессе поиска значения на хранимых ключах вызывается метод <K as Borrow<Q>>::borrow, и результат возвращаемого значения сравнивается со значением, переданным в get. Именно благодаря этому API (и реализациям в std, разумеется) коллекцию HashMap<String, Thing> можно индексировать значениями типа &str.

Но у этого API есть недостаток. Именно, оно требует, чтобы предоставляемое значение было ссылкой и чтобы из ссылки на ключ можно было получить ссылку на Q. Это ограничивает применимость API. Если, например, в мапе в качестве ключей хранятся (String, String), то логичный невладеющий эквивалент для индексации (&str, &str) не будет работать, потому что это кортеж ссылок, а не ссылка.

В короткой статье Borrowed tuple indexing for HashMap рассказывается, как с некоторым количеством бойлерплейта можно обойти это ограничение.

Для сравнения, hashbrown (поверх которого сделаны мапы в std) от подобных ограничений не страдает, поскольку там в API используется более гибкий трейт Equivalent:

trait Equivalent<K>
where
K: ?Sized,
{
fn equivalent(&self, key: &K) -> bool;
}
👍9🤯2🤡1