1.92K subscribers
3.6K photos
137 videos
15 files
3.81K links
Блог со звёздочкой.

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

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
👍8❤‍🔥1😁1
POSIX позволяет создать и использовать хэш-таблицу!

Но только одну

Source

#prog #suckassstory
🤡21🤯9😱3
#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 #rust #gamedev #amazingopensource (но пока сырое)

Revy is a proof-of-concept time-travel debugger for the Bevy game engine, built using Rerun.

Revy works by snapshotting diffs of the Bevy database every frame that are then logged into the Rerun database.
This allows you to inspect and visualize the state of the engine at any point in time, either in real-time or after the fact.
These recordings can then be shared to be replayed or e.g. attached to bug reports.
👍7🤔31
#prog #meme про мамку

Source
😁25💯3🤡1🤨1
#prog #rust #rustreleasenotes

Вышла версия Rust 1.93.0! Как обычно, тут только избранное, остальное только в детальных заметках о релизе.

(да, я выкладываю анонс с опозданием больше недели, и что ты мне сделаешь?)

В этот раз большинство изменений связаны со стандартной библиотекой.

▪️Немного печальное изменение: даже с установлением #[global_allocator] std всё ещё может вызывать System аллокатор. По крайней мере, на core это не распространяется.

▪️Компилятор теперь выдаёт предупреждение на #[repr(C)]-перечисления, у которых значения дискриминантов не умещаются в сишный int. Смешно, но до C23 у сишных enum нельзя было указать численный тип и нельзя было использовать значения больше int для дискриминантов.

▪️Компилятор теперь выдаёт предупреждение на попытку вызвать метод на const-значении, который эксплуатирует внутреннюю изменяемость. Так как константы инлайнятся по месту использования, эти изменения не будут видны. Обычно это является следствием ошибки — использования const вместо static (и я, кстати, такую ошибку уже делал).

▪️Метод append на BTreeSet и BTreeMap теперь сохраняет ключ из исходной коллекции, если ключи считаются равными через ==. До этого перезаписывались и ключ, и значение.

▪️Стабилизированы API:

🔸assume_init_drop, assume_init_ref и assume_init_mut на MaybeUninit<T>
🔸write_{copy, clone}_of_slice на [MaybeUninit<T>]
🔸into_raw_parts на String и на Vec. Странно, что только сейчас, потому что обратные from_raw_parts методы были стабилизированы ещё в версии 1.0.
🔸методы для непроверяемых (и потому потенциально дающих UB) битовых сдвигов в обе стороны на примитивных числах, а на знаковых — ещё и unchecked_neg
🔸методы для перевода ссылок на слайсы в (опциональные, разумеется) ссылки на массивы и сырых указателей на слайсы в сырые указатели на массивы, включая мутабельные варианты
🔸pop_front_if и pop_back_if на VecDeque
🔸std::fmt::from_fn для ad-hoc форматирования через переданную функцию. Позволяет избежать создания одноразовых типов, нужных только для форматирования

▪️Cargo теперь прокидывает значение конфигурации debug_assertions в билд-скрипты.

▪️Команда cargo tree теперь позволяет использовать для форматирования записей в дереве длинные имена для элементов шаблонов. Например, следующие два вызова эквивалентны:

cargo tree --format='{p} {f}'

cargo tree --format='{package} {features}'

▪️cargo clean теперь может удалять артефакты компиляции из всего workspace-а целиком.
👍8😁1
#prog #suckassstory
So much for "plain text" API

PSA: Did you know that it’s unsafe to put code diffs into your commit messages?
Like https://github.com/i3/i3/pull/6564 for example
Such diffs will be applied by patch(1) (also git-am(1)) as part of the code change!
This is how a sleep(1) made it into i3 4.25-2 in Debian unstable


Source

(thanks @itpgchannel)
😁11🌚3
#prog #моё

У метода Iterator::all — который возвращает, удовлетворяют ли все элементы в итераторе переданному предикату — есть вот такая строчка в документации:

An empty iterator returns true.


Более того, аналогичное утверждение есть и в документации метода allMatch на Java Stream API, и в документации встроенной функции all в Python, и в документации IEnumerable.All в C#. Некоторые странные люди утверждают, что all на пустой последовательности должен возвращать false — дескать, нет значений — не возможности определить значения.

Я здесь для того, чтобы сказать, что эти люди неправы.

Условный all(seq, pred), где seq — это последовательность a1, a2, ..., an, вычисляет значение pred(a1)∧ pred(a2) ∧ ... ∧ pred(an) (∧ — символ коньюкции, который в ЯП часто называют &&). Коньюкция — операция коммутативная и ассоциативная, поэтому если последовательность s является конкатенацией последовательностей a = a1, a2, ..., an и b = b1, b2, ..., bn, то мы можем переставить скобки и посчитать

all(s, pred) = pred(a1) ∧ ... pred(an) ∧ pred(b1) ∧ ... ∧ pred(bn)

как

(pred(a1) ∧ ... pred(an)) ∧ (pred(b1) ∧ ... ∧ pred(bn)) = all(a, pred) ∧ all(b, pred)

Или, иными словами и в синтаксисе Rust, если x и y — итераторы, то логично ожидать, что x.chain(y).all(p) вернёт тот же результат, что и x.all(p) && y.all(p).

Это свойство должно работать для любых последовательностей, включая пустые. С другой стороны, любую последовательность можно представить, как конкатенацию этой же последовательности с пустой. Или, в синтаксисе Rust, с поправкой на типы x и x.chain(iter::empty()) ведут себя одинаково. Подставив это в свойство выше, мы получаем, что x.all(p) && iter::empty().all(p), x.chain(iter::empty()).all(p) и x.all(p) должны возвращать один и тот же результат. Для произвольного итератора x это возможно только в том случае, если iter::empty().all(p) возвращает значений, нейтральное для коньюкции, то есть true. Иными словами, Iterator::all должен возвращать true на пустом итераторе, ч. и т. д.

Аналогичные соображения показывают, почему Iterator::any должен возвращать false.
💯28🤝10❤‍🔥3🤡2
#prog

В #go тесты работают таким образом: программист делает файлы, имя которых оканчивается на _test.go, и внутри пишет функции вида:

func TestXxx(*testing.T)


(префикс Test обязателен), а команда go test автоматически эти тесты подхватывает и исполняет. Тип testing.T позволяет организовывать тесты: логгировать, запускать подтесты и досрочно прерывать тесты, как ошибочные.

К чему я это? В последней версии Go — Go 1.26.0, вышедшей 10 февраля — есть несколько изменений. Одно из них — у кучи функций из подпакетов пакета crypto описаны изменения в духе "функция для генерации ключей теперь игнорирует аргумент, переданный для генерации случайности, и использует криптографически безопасный источник случайности". Разумеется, для тестов желательна воспроизводимость. Но как этого добиться, если источник случайности игнорируется?

Для решения этого вопроса Go предлагает два решения.

Первое — это GODEBUG, костыль способ заставить программы на Go (скомпилированные!) использовать поведение из более старой версии. В данном случае предлагают добавить настройку cryptocustomrand=1. Настройки через GODEBUG не вечные и могут быть убраны в одном из будущих релизов. По этой причине этот способ выглядит не особо привлекательным.

Второе — это использовать новую функцию testing/cryptotest.SetGlobalRandom. Она устанавливает сид для источника случайности, который будет использоваться для всех криптографических функций из пакета crypto, полагающихся на случайные данные. Эти изменения действуют в пределах одного теста, запускаемого testing.T. Соответственно, для каждого теста, который желает воспроизводимости, эту функцию нужно вызывать явно в начале. Разумеется, как справедливо отмечено в документации,

Because SetGlobalRandom affects the whole process, it cannot be used in parallel tests or tests with parallel ancestors.


Воистину concurrent programming language!
🤮24😁10🤩3
#prog #article

BTW PVS-Studio развивают версию своего анализатора для #go, и хотя для широкой публики анализатор ещё не доступен (в апреле будет бета-версия), он уже находит множество ошибок, которые не находит go vet. Все найденные ошибки при этом на Go не завязаны, так что, возможно, в будущем анализатор станет ещё полезнее конкретно для Go.
👍9
Random Rust Dev
Как заставить растовика задуматься над элементарной вещью?

Задайте ему вопрос: Какой тип у `0x12345_f32`?
#prog #rust

Но вообще ответ не вполне корректен. Тип числового литерала уточняется выводом типов, а конкретно i32 выбирается только в том случае, если ограничений на тип недостаточно, чтобы выбрать конкретный числовой тип (и лично я это считаю недостатком Rust)
🤔7👍3
#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;
}
👍10🤯3🤡1
😁14🤯10🍌3💯1
#prog #rust #article

Making cargo-semver-checks faster - Google Summer of Code 2025

Overall, I reduced the typical runtime on very large crates down to ~2s from ~8s - nearly an 80% speedup - without compromising performance on smaller crates. Along the way I reduced test time from ~7min to ~1min.
6
#prog #article

Compendium: A Linux Syscall Tracer

Having a love-hate relationship with strace I ended up yearning for something new.

Enter Compendium: a friendlier strace-like tool, with sane defaults, that optionally produces a clean html report that you can view in your browser of choice.

It tracks file descriptors across their lifetime, distinguishes files from sockets, aggregates I/O stats, registers events for memory operations (both vm and actual page faults), threads/subprocesses and more in real time and produces a summary at the end.
👍13
😍7🤣4🥴2🤯1👌1🌚1
#prog #sql

From 19k to 4.2M events/sec: story of a SQLite query optimisation

1. Знай свои данные, чтобы не делать линейный скан почём зря.
2. Небольшой кеш в памяти может снизить число запросов с n до константного.
😭3🤔2