Минутка просвещения

Читать в телеге. Когда-то там были посты не только от меня.

DSL для роутинга

В Spring 5.2 можно писать в функциональном стиле не только для WebFlux, но и для обычного MVC. Т.е. вместо анноташек над контроллерами можно писать что-то вроде

fun routes() = router {
    accept(ALL).nest {
        GET("/hello/{name}") {
            val name = it.pathVariable("name")
            ok().body("Hello, $name!")
        }
    }
}

где лямбды принимают ServerRequest и возвращают ServerResponse. Такой подход можно использовать для генерации эндпоинтов из конфига.

Подобный подход очень напоминает Ktor:

    routing {
        get("/hello/{name}") {
            val name = call.parameters["name"]
            call.respondText("Hello $name!")
        }
    }
СсылкаКомментировать

Модели памяти языков программирования

Хорошая, хоть и длинная, статья про то, какие проблемы могут быть с точки зрения распространения изменений данных при многопоточной обработке, от создателя языка Go. Есть еще и первая часть, про те же проблемы с точки зрения процессоров, но она поскучнее и менее интересна (большая часть кратко повторена в программной части).

В хардварной части в основном рассматриваются разные ситуации с гонками и последовательной согласованностью (Sequential consistency). Раскрывается мысль, что даже на уровне железа есть приколы с многопоточностью. Получается, что очень похожие проблем с параллелизмом случаются в разных контекстах и на разных уровнях абстракций: в процессоре, языке программирования, узлах распределенной БД, микросервисах. И методы решения похожи: куча очередей (как в x86), куча синхронизирующихся копий состояния (как в ARM). Разумеется, x86 и ARM дают разные гарантии консистентности. Под конец статьи рассказывается о модели синхронизации DRF (data-race-free). Вкратце суть такая: кроме чтения и записи, для памяти есть еще операция синхронизации. Сихнронизация служит “барьером”: операции чтения и записи можно перемешивать как угодно, но нельзя перемещать через барьер. И в 1990 доказали, что если писать программу без гонок (нормально синхронизировать чтение-запись между потоками), то тогда на железо, соответствующее DRF, будет выполнять с последовательной согласованностью, т.е. как будто она вся выполнялась в одном потоке. И это очень классный результат, потому что позволил абстрагироваться от кучи проблем, написанных в начале статьи, и дать хоть какой-то простор для оптимизаций компилятору.

В программной части больше интересного. Например, Java, оказывается, первый язык, в котором была попытка прописать поведение многопоточных программ на уровне спецификации (1996). С первого раза не получилось, но в 2004 в Java 1.5 добавили фич и она стала поддерживать модель DRF, причем в этом активно участвовала одна из авторов оригинальной статьи. Отношение happens-before как реализация DRF — важная часть модели памяти Java. Однако создатели в 2010 году признали, что у этой реализации есть баги, хоть она и является хорошим компромиссом между сложностью и надежностью.

В C++11 использовали модель Java как основу (sic!), пытались сделать проще, но в итоге только усложнили и она стала менее полезной для программистов. Ну и undefined behaviour добавили, куда ж без него, и стремные атомики, которые особо ничего не гарантируют. Однако в Си, Rust и Swift использовали модель C++11 (последние два — потому что LLVM и интеграция). JavaScript пошел своим путем: его модель памяти совместима с C++11, но ближе к Java (место для вашей шутки про название языка).

Хоть автор и с оптимизмом смотрит в будущее, текущая ситуация с моделями памяти тяжелая: до сих пор не предложена модель конкурентных вычислений с примитивами для корректной быстрой синхронизации памяти, и никто до конца не понимает и не может формализовать гонки.

СсылкаКомментировать

Запуск графического приложения с админскими правами

Раньше для этого можно было вызвать команду с gksu, например gksu kse. Однако, gksu убрали из дистрибутивов, т.к. он не безопасен.

Альтернатива — использовать политики (для параноиков) или pkexec. Но есть проблемка: при подтверждении запуска виден только исполняемый файл, но не его аргументы. Т.е. окно авторизации для pkexec sh -c 'echo hello' и для pkexec sh -c 'rm -rf /' будет выглядеть одинаково. Решить это можно через политики, но писать душный xml — скучно, поэтому можно извратиться по-другому.

Можно отредактировать сообщение сервиса polkit, вставив туда шаблон $(command_line). Для этого:

  1. Берем файл с переводом для британского языка и распаковываем его msgunfmt /usr/share/locale-langpack/en_GB/LC_MESSAGES/polkit-1.mo -o polkit-1.po
  2. Редактируем polkit-1.po любым текстовым редактором, добавляя в msgstr Authentication is needed to run '$(program)' ('$(command_line)'), msgid не трогаем.
  3. Пакуем отредактированный файл обратно, в директорию со своей локалью (у меня это en_US) msgfmt polkit-1.po -o /usr/share/locale/en_US/LC_MESSAGES/polkit-1.mo
  4. Рестартуем сервис polkit, чтобы изменения применились: systemctl restart polkit

После этого можно будет увидеть полную команду, которую кто-то хочет выполнить с правами супер-пользователя. Ибо нечего авторизовывать что попало, а то какой-нибудь дропбокс любит запрашивать таким макаром право на запуск баш-скрипта, который меняет владельца и права на свои папки.

СсылкаКомментировать

Неявная конкатенация строк в Python

В питоне есть баг фича, что строковые литералы, написаные рядом, автоматически соединяются в один:

>>> print("ololo" "alala")
ololoalala

>>> ["1" "2", "3"]
['12', '3']

Иногда это может очень бесить (и не только меня, но PEP с предложением выпилить это наследие Си отклонили). Теоретически, помочь могут линтеры: pylint или flake8. А тут можно посмотреть примеры, почему такое поведение может быть полезным.

СсылкаКомментировать

Тестирование распределенных систем

В продолжение постов про Jepsen и чек-листы по архитектуре микросервисовресурс, на котором собрана полезная информация про тестирование распределенных систем (в т.ч. всеми любимых микросервисов).

СсылкаКомментировать

Уровни языков программирования

Был в Академгородке на выставке “Наука Сибири”, там попалась книжка 2015 года про парадигмы программирования. В оглавлении встретились “языки низкого уровня”, “языки высокого уровня” и … “языки сверхвысокого уровня”. “О таком я еще не слышал, — подумал я, — наверно, это про какой-нибудь Haskell или Prolog, которые сильно абстрагированы от железа. Или про DSL?”

Но оказалось, что сибирские ученые таким языком считают Sisal — еще один достаточно специфичный язык для параллельных вычислений, который позволяет не заботится о синхронизации и разбивке на отдельные процессоры/компьютеры. Он является “функциональным потоковым языком, ориентированным на написание больших научных программ”, “одним из самых известных потоковых языков промышленного уровня”, “позиционируется как замена языка Fortran для научных применений” и позволяет “предоставить широкому кругу прикладных программистов, не имеющих достаточного доступа к параллельным вычислительным системам, но являющихся специалистами в своих прикладных областях, возможность быстрой разработки высококачественных переносимых параллельных алгоритмов на своем рабочем месте”. Создан язык в 1983 году, вторая версия вышла в 1991, а в ИСИ СО РАН развивают этот язык после третьей версии, уже даже cloud-версия есть. По синтаксису напоминает Pascal.

Что такое язык сверхвысокого уровня, я в итоге и не понял (но можете попробовать вы, начать можно отсюда, осторожно, опасно для мозга), но по идее Erlang, любой язык с акторами, Spark DSL — это все языки сверхвысокого уровня в данной терминологии.

Любопытно, что Википедия языками сверхвысокого уровня считает Python и Visual Basic. Правда, это термин из 90х, когда Си был языком высокого уровня (а сегодняшний программист скорее выделит для него “средний” уровень). А еще можно почитать про поколения языков программирования, где первое поколение — машинные коды, третье — С++, Java и т.п., а пример четвертого — 1C. Такие дела :)

СсылкаКомментировать

Альтернативы классическому менторству

Делал презентацию для встречи, чтобы вбросить пищу для размышлений по теме менторства, но встреча перенеслась непонятно куда, поэтому почему бы и не выложить ее сюда.

В ней нет никаких глубоких изысканий, да и делал ее я в основном для того, чтобы поиздеваться над первой фразой от коллеги (:toxic:).

СсылкаКомментировать

Чек-лист тимлида

Хорошая статья, которая пригодится не только всяким руководителям, но и каждому в команде. В ней рассмотрены типичные боли проекта и команды с позиции “что можно улучшить новому руководителю”, но можно использовать ее как источник идей для того, что можно улучшить в команде самостоятельно. Содержит жизы :)

СсылкаКомментировать

16 Кб хватит всем

У докера обнаружилась веселая особенность: он разделяет строки лога длиной более 16 Кб, чтобы оптимизировать использование буфера. Настроить размер нельзя. При разбиении лог помечается как разделенный, и подразумевается, что склейка должна быть на стороне агрегатора логов (причем есть несколько их реализаций). Однако не все агрегаторы это адекватно поддерживают: например, Filebeat не может это сделать для двух записей из разных файлов (в разные файлы они могут попасть при ротации логов).

СсылкаКомментировать