1.84K subscribers
3.27K photos
130 videos
15 files
3.55K links
Блог со звёздочкой.

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

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

Какой же ор
Forwarded from partially unsupervised
Почему в software engineering так сложно с оценками сроков? Потому что зачастую практически невозможно на глазок оценить глубины кроличьей норы, если речь идет о чем-то сложнее перекраски кнопки на лендинге.

Вот небольшой пример. Есть сервис на питоне, в котором некоторые запросы начали тормозить. Хочется найти эти запросы, для этого - добавить в логи какой-то request_id.

Но в мире асинхронного питона нельзя просто хранить какой-то id на уровне треде, т.к. тред может переключаться между запросами в процессе await, нужно использовать ContextVars. Чтобы прикрутить ContextVars, нужен Python 3.7+, нужно обновиться. В процессе обновления выясняется, что некоторая старая версия библиотеки официально не поддерживает новый питон, нужно собрать ее руками. Методом проб и ошибок находим коммит, с которого собиралась старая версия для старого питона, собираем для нового питона - результаты не сходятся, тесты падают!

Для начала нужно собрать минимальный воспроизводимый пример (в моем случае получился Dockerfile на 50 строк и примерно столько же Python-кода). Разбираем билд и видим, что библиотеке нужен с десяток shared зависимостей, для которых не всегда указаны версии. Можно найти какие-то древние логи на CI-сервере, который собирал библиотеку для старого питона, и из них достать какие-то куски информации. Их не хватает, и версии приходится перебирать бинарным поиском. Версии подобраны, они конфликтуют друг с другом, и склеить их вместе можно только странным перебором apt install ... && apt remove ... && apt install.

На все эти развлечения ушло уже три дня, и я не могу сказать, что приблизился к заветным request_id. А ведь сторонний наблюдатель с навыками эффективного менеджера вполне мог бы возмутиться: "че там делать вообще? завел переменную и клади в лог, делов-то".
Forwarded from partially unsupervised
Иронично, что даже в этом примере кроличья нора в итоге оказалась ощутимо глубже, чем я думал.

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

Здесь могла быть классическая картинка про многопоточность.
Хочешь зарабатывать много денег? Мечтаешь войти в высшую лигу разработки? Хочешь войти в IT, но не знаешь, как начать?

Сочувствую.
🔥1
— %внутренний компонент% — это %внутренний компонент%, а это — это это.

#quotes #трудовыебудни
Читаю тут, почему строки в Java и C# иммутабельные. Фактически, ответ — потому что языки г... Недостаточно мощные и не могут гарантировать ни thread safety, ни иммутабельный доступ к объектам. А вы говорите, что borrow checker не нужен.
👍1
Блог*
Читаю тут, почему строки в Java и C# иммутабельные. Фактически, ответ — потому что языки г... Недостаточно мощные и не могут гарантировать ни thread safety, ни иммутабельный доступ к объектам. А вы говорите, что borrow checker не нужен.
Кстати, в Java 7 поменяли семантику метода substring: раньше новая строка переиспользовала хранилище оригинальной строки, а после этой версии делает новую строку в хипе. Оба варианта так себе: первый использует слишком много памяти, если подстрока берётся от очень большой строки (старая-то никуда не девается, новая ссылка не даёт сборщику мусора собрать старую строку) — собственно, это и было причиной для внесения изменений, а новый вариант потребляет излишнюю память, если программа оперирует большим количеством подстрок одной и той же строки (скажем, в программе какой-то свой парсер).

Новый вариант, кстати, строго хуже: в старом варианте можно было форсировать выделение в куче при помощи костыля вида string sub = original.substring(from, to) + "";, а при помощи нового варианта получить поведение, как в старом варианте, нельзя.
Блог*
Читаю тут, почему строки в Java и C# иммутабельные. Фактически, ответ — потому что языки г... Недостаточно мощные и не могут гарантировать ни thread safety, ни иммутабельный доступ к объектам. А вы говорите, что borrow checker не нужен.
А вот ещё пример из Go. Мутабельных строк там нет (есть лишь string.Builder). Строка в рантайме — это структура с двумя полями: адрес и длина, а слайс — структура с тремя полями: адрес, длина и ёмкость. Технически ничто не мешает преобразовать слайс байт в строку, просто отбросив поле Cap (что, собственно говоря, и происходит в strings.Builder.String), но в общем случае это некорректная операция, потому что слайс мутабельный (всегда, иммутабельной версии слайса просто не существует), а строка — нет. Как результат, каст слайса байт в строку выделяет память в куче и копирует данные. Это лишняя работа, особенно если используемая строка почти сразу отбрасывается — например, если строка используется как ключ для map. В какой-то момент в компилятор Go запилили peephole-оптимизацию, которая распознавала паттерн someMap[string(bytesSlice)] и переписывала на реальный каст на фейковый, который просто копирует указатель и длину из слайса.
🤣2
Forwarded from rusta::mann
У меня новый фаворит среди изменений, предложенных ревьювером.

Code Review might not make your code better, but it definitely will make it doper.

#codereview
👍1
#prog #rust #rustlib

Библиотека (и плагин для cargo), которая позволяет найти минимальную версию Rust, с которой проект собирается. Использует, увы, линейный поиск вместо бинарного.

https://github.com/foresterre/cargo-msrv
Forwarded from Zero Dereference
A simple and well-documented microkernel operating system released under public domain.

https://resea.org/
👍1
Блог*
#prog Переписал по работе одну утилиту для анализа логов. Раньше для разбора строк использовались регулярные выражения, а я заменил на наколенный лексер. В результате утилита, которая почти 23 гигабайта перемалывает за чуть больше, чем за 5 минут, стала на…
В утилите (после моих изменений) используется массив строковых значений, с которыми строчки логов должны обрабатываться отдельно. Для более быстрого поиска этот массив упорядочен, а значение ищется бинарным поиском. На код-ревью коллега мне совершенно справедливо указал, что отсортированность нужно как-то поддерживать. Не вопрос: пишем const fn is_sorted(strings: &[&str]) -> bool — благо после релиза Rust 1.46.0, разрешившим циклы в const fn, это весьма легко — и пишем отдельно константу const _ASSERT_IMPORTANT_ARRAY_IS_SORTED: [(); 1] = [(); is_sorted(&IMPORTANT_ARRAY) as _]; — и теперь программа не собирается из-за несоответствия типов, если массив не отсортирован. Проблема решена.

К сожалению, сравнение строк в const fn пока использовать нельзя, так что константную функцию сравнения строк пришлось писать самому 😠
Forwarded from Linker Unsafe
Мой новый рисунок компилятором по консоли
Пока среда не закончилась