Читать в телеге. Когда-то там были посты не только от меня.
HEAD
У меня случайно был включен Caps Lock, и вместо head s<Tab>omefile
я напечатал HEAD S<Tab>omeOtherFile
. ВНЕЗАПНО, HEAD
это валидная команда, так же как и GET
и POST
— это утилита lwp-request, которая, по сути, аналог curl
, причем еще написанный на перле! Судя по всему, это стандартный пакет Debian.
Вычисление двоичного логарифма
Найти ответ на вопрос, как в стандартной библиотеке реализовано вычисление логарифма, оказалось сложнее, чем можно подумать. Во-первых, алгоритмов вычисления довольно много: от наивной итерации по Тейлору до хитрых методов с таблицами. Во-вторых, реализация будет отличаться в зависимости от архитектуры процессора, наличия векторизации (SIMD, SVE и прочие страшные аббревиатуры) и от авторов библиотеки (GNU, musl, UCRT и т.п.).
Если смотреть на среднебольничную реализацию, то это будут математические преобразования по сужению области определения, набор предвычисленных таблиц и вычисление 5-7 членов ряда Тейлора. Некоторые процессоры имеют встроенную команду fyl2x
для x * log2(y)
, и она даже используется, правда она может выполнятся довольно медленно: на некоторых старых процессорах — больше 1000 тактов, а в среднем за 50-100 тактов.
При этом двоичный логарифм довольно особенный. Если работать с числами с плавающей точкой и нам не очень важна дробная часть, то можно просто взять показатель двоичной степени при помощи frexpf
. А если работаем с целыми числами, то достаточно знать позицию первой единицы слева или количество нулей слева — для этого у некоторых процессора есть команды bsr
и/или clz
соответственно, а в GCC — встроенная функция __builtin_clz
.
Будущее эффектов
Интересная статья про будущее работы с эффектами в Scala. Это своего рода продолжение обсуждения про добавление suspend
-функций и про новые подходы к обработке ошибок.
Один из главных выводов статьи: асинхронные функции — это решение проблемы, однако у сообщества нет четкого и однозначного понимания, в чем эта проблема состоит (без внятного ТЗ результат ХЗ).
В статье затронуты такие проблемы как много способов сделать одно и то же в Scala, несовершенство двухцветной реализации корутин в Kotlin и трактовку RPC как локальных функций. Открыт вопрос, надо ли делать решение только под JVM или под все платформы, и должно ли решение быть на уровне языка или библиотек.
Для постановки проблемы нужно понять:
- Должны ли эффекты фигурировать в сигнатуре метода? Почти все в сообществе склоняются к “да”.
- Должна ли эта информация распространятся на вызывающие методы вплоть до точки входа? А вот тут мнения разделяются.
- Что вообще надо отслеживать? Это занятно пересекается с п.1 Нужно ли учитывать асинхронность вычислений? А с учетом Loom? Любой ввод-вывод? Ошибки?
Обсуждение все еще в процессе. А еще Одерски запустил исследовательскую программу Caprese для поиска способов отслеживать эффекты, так что может что-то новое оттуда родится.
Рефлексия и продуктивность
Интересное исследование от GitHub про то, что нужно разработчикам, чтобы быть продуктивными и чувствовать, что день был прожит не зря. Много довольно очевидного, но тут хотя бы есть какие-никакие экспериментальные данные. Из довольно капитанских выводов:
- Состояние потока это важно, должно быть выделенное время для сосредоточенной работы
- Больше двух встреч в день — это рак, 1 встреча — норм.
- Даже оформление пулл-реквеста — это выход из потока.
- Больше времени в состоянии потока — больше достижений и меньше стресса.
Менее очевидный вывод: разработчики, которые ежедневно тратили пару минут в конце дня, чтобы порефлексировать, был ли день хорош и почему, начинали ДУМАТЬ и они даже что-то меняли в итоге в своем подходе к работе.
Когда я впервые столкнулся с agile, я писал себе коротенько, что делал за день, чтобы потом на стендапе не надо было вспоминать. Но вскоре я, к сожалению, в этом разочаровался: увы, большинству людей абсолютно насрать, че ты там делал, проквакал че-то нормальное и пофиг. До agile я записывал только свои достижения. Вот это полезно, и я продолжаю везде это делать. На Performance Review ты молодец-огурец, кучу всего достиг и ничего не забыл. Да и в резюме есть что записать.
"Понятность" java
Очень часто чуть ли не единственным техническим аргументом в пользу использования java, а не какого-нибудь высокоуровневного языка, слышу что-то вроде “ой, ну вот с этим синтаксическим сахаром ничего не понятно, вот на java все просто и логично, там легко читать и все понятно”.
Вот отличный видео ответ этим “простакам”: да, там “паззлеры”, но не какие-то хитровычурные, а вполне себе обычный код, который может попасться при работе с коллекциями.
Ноутбук как монитор
В продолжение темы про мониторы. Пришла в голову бредовая мысль попробовать как-нибудь использовать личный ноут как второй экран для рабочего мака. Думал, что тут будут вовлечены какие-нибудь провода и специальное ПО, но оказалось, что есть довольно интересное решение — создать виртуальный экран и расшарить его по сети.
Для создания виртуального экрана есть даже специальные HDMI-затычки и масса программных вариантов. Из них я попробовал 2:
- DeskPad — ноль настроек, запустил и готово. Но экран только один.
- BetterDisplat — настроек до фига. Но при запуске какого-то черта меняет настройки основного экрана. И хотя тут можно добавить больше одного виртуального экрана, я не разобрался, как сделать так, чтобы они не были зеркалом друг друга.
Шарил экраны с помощью Deskreen. Что тут сказать… вроде работает, но мыльно и тормознуто: лаг довольно заметен. Что интересно, я пробовал еще подключать iPad как третий монитор, и там лаг меньше. Еще совсем не помогало, что у личного ноута 16:10, iPad 4:3, а у мака вообще 1800x1169 — этот зоопарк либо обрезался, либо растягивался (возможно это можно настроить нормально, но из коробки работало так себе).
Столкнулся с проблемой, что окно не может быть на нескольких экранах одновременно, но оказалось, что это решается настройками мака. Кроме этого, было два случая, когда “все сломалось”:
- Когда в настройках мака сделал виртуальный экран основным, то маковский экран “завис”, а ноутный просто отвалился. Хорошо, что на iPad был запущен терминал, через который я прибил виртуальные экраны.
- Когда открыл окно на полный экран, мак сходит с ума и на своем экране показывает черноту, а на остальных получается либо статическая картинка, либо артефакты.
Паравозик между разными экранами я в итоге запустил (но понадобилось запускать два разных приложения для виртуального экрана, чтобы не было зеркала).
В общем, great idea, does not work.
awk
Недавно понадобилось сделать простую операцию над текстовым файлом: посчитать минимальную/максимальную длину строки. Звучит элементарно, ща быстренько состряпаем что-нибудь из cat
+ wc
+ sort
… Только надо подобрать правильную комбинацию параметров и xargs
вставить. С наскока, разумеется, не получилось. На питоне ради этого писать лениво, и в итоге на StackOverflow было найдено решение с awk
:
awk '{print length}' input.txt | sort -rn | head
На чистом awk
минимум будет выглядеть так (решение предложено ChatGPT):
awk 'NR == 1 || length < min { min = length } END { print min }' input.txt
Еще проще будет посчитать среднюю длину строки:
awk '{total += length} END {print total/NR}' input.txt
Раньше я обычно игнорировал решения на awk
, потому что они были не очень понятны в отличие от различных комбинаций grep
, sed
, cut
, wc
, sort
и прочих: они достаточно простые, и “делают одну вещь хорошо”. А если что-то серьезное возникало — то писал что-то на питоне.
Но после описанного случая решил немного почитать про awk
и, оказывается, он из коробки поддерживает построчную обработку (питонячий бойлерплейт), разбивку на поля (cut
) и регулярки (grep
/sed
). Достигается это за счет довольно интересной концепции: каждая строка проверяется по паттерну(ам) — условию/регулярке, и если она соответствует, то выполняется действие в фигурных скобках. В общем, планирую попробовать.
Хотя можно не париться и просто ChatGPT попросить скрипт написать.
Сколько мониторов нужно для счастья
За время своей работы встречал разнообразные мнения по данному вопросу:
- Нужно 4 монитора! На одном реверсить, на другом даташит открыт, на третьем среда разработки, на четвертом разводка платы… Больше мониторов богу мониторов!
- Два монитора норм, на одном кодишь, на другом открыт тикет/чат/
порнуха/унылый созвон. Или запускаешь созвон на одном экране, а другой шаришь. - Нужен только один монитор (но большой), потому что если много мониторов — теряешь фокус на одной задаче.
Когда-то мне казалось, что надо 3 монитора, но сейчас я склоняюсь к умеренному варианту №2, причем это экран ноута + монитор. На одном большом экране даже со всякими приемами разделения окон может быть не очень удобно переключаться между контекстами (а на маке разделение экрана само по себе конченое). А двух экранов достаточно, чтобы выполнять переключение поворотом головы.
Вообще, переключение контекста — довольно дорогая операция. И если их нужно одновременно больше двух, то, возможно, вы что-то делаете не так? Может надо сделать какую-то предварительную обработку “вспомогательных” контекстов, чтобы они работали как один?
А что говорит по этому поводу наука? Нашел мета-исследование на тему (по DOI можно найти на сцихабе полный текст). Если смотреть на опросы пользователей, то там все понятно: минимум 17”, большинству подавай два монитора. Однако кто говорил, что ему надо четыре, не использовал их по полной. Если смотреть на более объективные измерения, то в одном исследовании измеренная продуктивность выше с двумя мониторами, чем с одним, но при этом третий монитор существенно на нее не влияет. В другом исследований не обнаружили разницу между одним и двумя мониторами 17” или 22” (зависит от задачи, в общем). При этом есть умеренные свидетельства уменьшения числа кликов/переключений окон при увеличении размера и количества мониторов.
Работа с файловой системой
Подобно тому, как стоит избегать писать свои реализации всякой криптографии и делать что-то со временем, есть еще одна область в которую лучше не лезть: работа с символическими ссылками и файловой системой вообще.
Правильно реализовать работу с символическими ссылками — довольно нетривиальная задача. Хорошую презентацию по этому поводу можно посмотреть тут. Если вкратце, то ссылки могут меняться между системными вызовами, что открывает массу возможностей для повышения привилегий из-за того, что их проверка и действие над ссылкой происходит неатомарно. Даже в системных вызовах Linux не смогли поправить это с первого и даже со второго раза.
А еще символические ссылки ломают иерархию (и связанные с ней проверки) — например, путь с ..
уже нельзя нормализовать без запроса к файловой системе. А еще ссылка может ссылаться на другую ссылку, и эти случаи в два раза веселее обрабатывать.
В добавок к этому, я недавно нашел интересное поведение в java. Если создать папку, содержащую юникодные символы, то ее имя по-разному будет нормализовано в зависимости от того, был ли использован метод Files.createDirectory
или File.mkdir
. Это приводит к тому, что оригинальный путь не совпадает с “реальным” путем к файлу, который только что был создан по этому пути:
package test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import java.util.function.Function;
public class App {
@FunctionalInterface
public interface Action {
void apply(Path path) throws IOException;
}
public static void main(String[] args) throws IOException {
check("createDirectory", Files::createDirectory);
check("mkdir", x -> x.toFile().mkdir());
}
private static void check(String hint, Action createDir) throws IOException {
String name = "teŝt files";
Path root = Path.of(name).toAbsolutePath();
Path file = root.resolve("file1");
Files.deleteIfExists(file);
Files.deleteIfExists(root);
createDir.apply(root);
Files.createFile(file);
Path alternative = file.toRealPath();
System.out.printf("%s - Equals: %s, isSameFile: %s\n", hint, file.equals(alternative), Files.isSameFile(file, alternative));
}
}
Вывод:
createDirectory - Equals: true, isSameFile: true
mkdir - Equals: false, isSameFile: true
Запись команд терминала
Чтобы записать демонстрацию какой-нибудь последовательности команд, можно воспользоваться Asciinema. Работает примерно так:
Можно конвертировать результат в гифку или использовать js-проигрыватель.
На удивление, эта штука без проблем сработала, когда я ее запустил внутри самой себя. В целом прикольно, но мне текстовый формат нравится больше — оттуда, как минимум, проще копировать. Еще один минус — вся тупка при записи записывается, т.е. нет нормализации: задержки и ошибки при печати команд тоже сохраняются. С другой стороны, за счет этого запись более “живая”.