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

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

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

Afternoon project: JPEG DCT text lossifizer

Чел сделал штуку (веб-приложение), которая применяет к тексту процесс, аналогичный сжатию с потерями в JPEG: разбирает текст как семпл на частоты, огрубляет их и собирает обратно.

Пара моментов:

В JPEG квантизация в основном огрубляет (и отбрасывает) высокие частоты. В случае же с текстом это приводило к слишком большой деградации, поэтому программа сначала отбрасывает низкие частоты.

Первоначальная реализация использовала ASCII-коды напрямую, но комментатор предложил другую кодировку, в которой символы со схожим написанием/звучанием имели близкие коды, и это положительно сказалось на читаемости сжатого текста даже с весьма большим огрублением.
🤯114🔥2
#prog #rust #article

In defense of lock poisoning in Rust

<...> I keep coming back to how unbounded the downside of an undetected panic is, and how easy it is to get wedged in this state. Mutexes and poisoning have value separate from each other, but I don’t think they are as independent as they seem at first. My understanding from writing Rust code over many years is that almost all uses of mutexes benefit from poisoning, and almost all instances of poisoning one needs to care about are with mutex-guarded data.
#prog #amazingopensource #article (и даже в какой-то мере #algo)

Stacktower.io (репозиторий) — инструмент для создания визуализаций зависимостей в духе известного комикса xkcd + история о его создании, с инкрементальным улучшением, начиная с брутфорса. История хорошо демонстрирует, насколько хорошо помогает знать prior art в computer science.
👍16🌚4❤‍🔥21
#prog #rust #rustreleasenotes

Вышла версия Rust 1.92.0! Как всегда, тут только интересные мне моменты — всё остальное в детальных заметках о релизе.

▪️Информация по оптимизации времени сборки теперь есть прямо в Cargo book 🎉 (PR)

▪️Линты про проблемы, связанные с never type fallback, теперь deny by default.

▪️Теперь на функциях можно комбинировать #[track_caller] и #[no_mangle]. Технически это можно было делать и раньше, но до этого релиза преобразование подобной функции в указатель на функцию сохраняло атрибут #[no_mangle], что приводило к ошибкам линковки. Если что, работает эта комбинация только на функциях с extern "Rust".

▪️Операции &raw const/&raw mut для взятия адреса теперь можно использовать на полях объединений в safe коде.

▪️Линт unused_must_use теперь не срабатывает на значениях Result<T, E>, где тип E не населён.

▪️Iterator::eq{, by} теперь может сделать ранний возврат на TrustedLen итераторах. Да, это означает, что теперь этот метод может отбрасывать операции с побочными эффектами.

▪️Методы count и last на iter::Repeat теперь паникуют вместо входа в бесконечный цикл.

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

🔸std::panic::Location::file_as_cstr (полезно для интеропа с C/C++)
🔸RwLockWriteGuard::downgrade для понижения блокировки на запись до блокировки на чтение
🔸new_zeroed и new_zeroed_slice на умных указателях. Сами конструкторы safe, потому что возвращают аллокации с MaybeUninit вместо значений напрямую.
🔸insert_entry на btree_map::Entry и btree_map::VacantEntry, которые вставляют переданное значение и возвращают OccupiedEntry (аналогичные методы для HashMap стабилизировали год назад)

▪️Методы rotate_left и rotate_right на слайсах теперь можно вызывать в const-контекстах.

▪️Поиск в rustdoc теперь скрывает методы трейтов на типах из результатов поиска, если в списке есть сам метод трейта. Например, поиск по "last" покажет Iterator::last и BTreeSet::last (метод на BTreeSet, не имеющий отношения к Iterator), но не покажет, скажем, std::vec::IntoIter::last.

▪️Компилятор теперь по умолчанию генерирует таблицы для раскрутки стека даже с -C panic=abort. Это сделано для рабочих трассировок стека (которые могут быть созданы не только паникой). Убрать эти таблицы можно ключём -C force-unwind-tables=no.
👍7🎉3
#prog #ml

github.com/perpetual-ml/perpetual

PerpetualBooster is a gradient boosting machine (GBM) algorithm that doesn't need hyperparameter optimization unlike other GBMs.

Hyperparameter optimization usually takes 100 iterations with plain GBM algorithms. PerpetualBooster achieves the same accuracy in a single run.
Вроде выглядит реальным
1
#prog #go #article #suckassstory

В стандартной библиотеке Go есть тип http.Client — HTTP-клиент. Одно из полей этого типа — Transport. Это поле хранит значение, которое занимается обработкой единичных запросов. Разумеется, для поля Transport есть значение по умолчанию — DefaultTransport. Но есть одна загвоздка.

Поле Transport — и, соответственно, DefaultTransport — имеют тип RoundTripper. Это интерфейс с единственным методом:

RoundTrip(*Request) (*Response, error)


DefaultTransport при этом на самом деле является значением типа Transport, у которого бОльшая часть полей является конфигурацией. На практике часто требуется скорректировать конфигурацию по умолчанию под нужды приложения (например, поменять таймауты). Но как это сделать?

Так как в Go нет констант (кроме чисел и строк), DefaultTransport является глобальной переменной пакета http. Соответственно, чтобы не поменять глобальную конфигурацию для всего, что использует http.Client (включая, возможно, код в зависимостях), нужно сначала сделать копию этой конфигурации. Более того, так как DefaultTransport имеет тип интерфейса RoundTripper, сначала нужно привести его к конкретному типу Transport. В итоге на практике во многих проектах на Go есть код наподобие этого:

t := http.DefaultTransport.(*http.Transport).Clone()
// Change properties
t.TLSHandshakeTimeout = time.Second
t.DisableKeepAlives = true


Элемент синтаксиса .(*http.Transport) является кастом интерфейса к конкретному типу, и так как синтаксически это не форма каста, которая возвращает два значения, это "небезопасный" каст, который паникует, если тип отличается от указанного.

Какая по итогу ситуация? Во множестве реально используемых программ на Go есть код, который трогает глобальную переменную (и, так как это Go, без синхронизации), полагается на неявное обещание другого кода эту глобальную переменную не трогать и платят за проверки типов при касте, не смотря на то, что тип так-то известен статически. В теории тот факт, что DefaultTransport является интерфейсом, позволяет поменять реализацию в будущем. На практике из-за существующего кода этого никогда не произойдёт, потому что сломает кучу работающего кода. Поменять тип DefaultTransport также нельзя, потому что это будет ломающим обратную совместимость изменение.

Очевидным выходом из этой ситуации является добавить функцию, которая будет возвращать значение DefaultTransport, как конкретный тип Transport. Соответствующее предложение поступило в мае 2020 года, однако воз и ныне там.
👍15😁9🤯1
#prog #article

On the purported benefits of effect systems

Don’t get me wrong, I think effect systems are cool because of the ability to define custom control flow operations in libraries.

However, the wide variety of purported benefits do not seem to stand up to close scrutiny.
👎3👍2
#prog

Для #java есть JEP 401: Value Classes and Objects (Preview). Value-объекты в данном случае — это объекты, у которых отсутствует идентичность. Это полезно, поскольку для многих классов, которые просто объединяют несколько полей вместе для удобства (например, LocalDateTime, или условной Point в графическом движке), наличие идентичности, отличной от совокупности значений, не имеет большого смысла.

На практике идентичность у объектов Java существует из-за того, что под них выделяется память в куче и, соответственно, у них есть уникальный адрес. Отсутствие такой идентичности позволяет генерировать более разумную реализацию оператора ==, а также делать то, что в JEP называется "heap flattening": изменение представление объекта, ссылки на который вместо хранения адреса выделенной памяти хранят значения полей объекта.

Всё это звучит хорошо, но, к сожалению, данная идея страдает от существующих элементов дизайна Java.

Первая — это повальная нуллабельность. Даже value-классы должны иметь возможность быть null, и это означает, что даже для сжатого представления один бит в ссылке должен отводиться под null-флаг. Как пишут сами авторы, массив из Integer, например, может хранить значения прямо в ссылках, но так как численные значения Integer занимают 32 бита и ещё один бит должен отводиться под null-флаг, на практике значения элементов массива будут занимать минимум по 64 бита. Это всё ещё выигрыш по сравнению с тем, что есть сейчас, поскольку это позволяет избежать индирекции на указателях и выделения 64 бита на заголовок каждого объекта в куче, но это всё ещё расточительно. Авторы явно признают эту проблему, и в разделе про дальнейшую работу есть ссылка на Null-restricted value class types JEP, но это пока лишь черновик.

Вторая проблема (которая, справедливости ради, была неочевидна индустрии на момент создания Java) — это отсутствие отслеживания алиасинга/перекрытия ссылок. В JEP авторы пишут:

Heap flattening must maintain the integrity of data. A flattened reference must always be read and written atomically, or it could become corrupted. On common platforms, this limits the size of most flattened references to no more than 64 bits.


Иными словами, выгоды от избегания аллокаций коснуться только очень маленьких объектов — особенно с учётом обязательного null-флага и паддинга под него. Но тут вообще стоит задать вопрос: зачем в принципе стоит требование атомарности обновлений ссылок? Атомарность нужна для того, чтобы избежать разрыва значений при одновременных обновлениях. Соответственно, если одновременных доступов нет, атомарность не требуется! Если бы в Java был механизм, который позволяет удостоверять, что доступ к значению уникален и остаётся уникальным в течение всего времени, пока значение остаётся достижимым (по крайней мере, для записи — многопоточное чтение безопасно и без атомарных операций), можно было бы использовать неатомарные операции для обновлений и избежать таким образом ограничений на размеры value-объектов. Можно считать это ещё одним примером к Fixing the next 10000 aliasing bugs, где инвариантом выступает целостность данных, и плюсом в копилку преимуществ отслеживания алиасинга для различных языков программирования.
🔥6😁3🤡3🤔1
#prog #article

Advent of compiler optimizations — сборник декабрьских статей, по одной в день (в обратном хронологическом порядке), демонстрирующих на отдельных небольших примерах различные оптимизации компиляторов. Написано Мэттом Годболтом (да-да, тот самый, который godbolt.org).
🔥72
#prog #rust #c #article

Eurydice: a Rust to C compiler (yes)

Eurydice is a compiler from Rust to C that aims to produce readable C code.


Сделано для интеграции кода на Rust в существующие проекты на C без того, чтобы требовать наличие двух параллельных реализаций.

Присутствует чуть-чуть джеркования:

Having a backwards-compat scenario where Rust can be compiled to C serves several purposes.
<...>
3. It allows for a census of problematic scenarios. By making the Rust version the default (and putting the fallback C behind a --write-us-an-email flag), there is finally a way to enumerate those mythical users who cannot switch to Rust just yet.
4❤‍🔥3
#prog #rust #rustlib

brie-tree - SIMD-optimized B+ Tree implementation that uses integer keys

A fast B+ Tree implementation that uses integer keys.
The API is similar to the standard library's BTreeMap with some significant differences:

* Lookups and insertions are 2-4x faster than BTreeMap.
* BTree can optionally be used as a multi-map and hold duplicate keys.
* Keys must be integer types or convertible to integers via the BTreeKey trait.
* The maximum integer value is reserved for internal use and cannot be used by keys.
* Elements in the tree are ordered by the integer value of the key instead of the Ord implementation of the keys.
* Cursors can be used to seek back-and-forth in the tree while inserting or removing elements.
* Iterators only support forward iteration.
👍10
#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 #itsec

MongoBleed explained simply

CVE-2025-14847 allows attackers to read any arbitrary data from the database's heap memory. It affects all MongoDB versions since 2017


Корень проблемы тот же, что и у Heartbleed. Баг не требует аутентификации для эксплуатации.

(thanks @jemalloc)
❤‍🔥1👍1😱1
#prog #rust #serde

serde's borrowing can be treacherous

(This is not super surprising when you think about it, but it bit me recently so I figured I'd write it up.)

TL;DR: Be careful when using &'a str or &'a [u8] with serde deserializers; serde has no way to produce an appropriate compile-time error when zero-copy deserialization isn't possible or just isn't supported. Instead, you'll get a runtime error indefinitely later.

Из-за экранирования данных, главным образом. Для обхода этой проблемы можно использовать Cow<'a, str> с #[serde(borrow)]
#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