Читать в телеге. Когда-то там были посты не только от меня.
Ноутбук как монитор
В продолжение темы про мониторы. Пришла в голову бредовая мысль попробовать как-нибудь использовать личный ноут как второй экран для рабочего мака. Думал, что тут будут вовлечены какие-нибудь провода и специальное ПО, но оказалось, что есть довольно интересное решение — создать виртуальный экран и расшарить его по сети.
Для создания виртуального экрана есть даже специальные 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-проигрыватель.
На удивление, эта штука без проблем сработала, когда я ее запустил внутри самой себя. В целом прикольно, но мне текстовый формат нравится больше — оттуда, как минимум, проще копировать. Еще один минус — вся тупка при записи записывается, т.е. нет нормализации: задержки и ошибки при печати команд тоже сохраняются. С другой стороны, за счет этого запись более “живая”.
Аннотации массивов в java
Психолог: заковыристые типы в Java не существуют, они не могут причинить тебе вреда.
Тем временем java: @Nullable List<? extends @Nullable Object> @NotNull [] @Nullable [] someVar
.
Вьетнамские флешбеки от сишных указателей.
Если серьезно, то массивы всегда были “особенными”: вроде и не примитивы, но и не классы. Еще и куча исключений, настолько, что это в Kotlin просочилось.
CRDT
Отличная интерактивная статья про CDRT (Conflict-free Replicated Data Type).
Это по сути фундамент для идей Клеппмана про Local-first приложения.
Двойные и тройные слеши в пути
Нашел прекрасное. В POSIX ////some/path
, ///some/path
и /some/path
— это одно и то же, но при этом не то же самое что //some/path
. 3 и более слешей спереди превращаются в одинарный слеш, а вот обработка 2 слэшей может зависеть от системы/реализации. И нет, это не из-за Microsoft.
В большинстве случаев, например в Cygwin, //host/path
интерпретируется как сетевой ресурс. Но не сетью единой: например, в Bazel //
используются для адресации таргетов.
Локальный запуск LLM
TLDR: Если вам нужен простой локальный GPT, попробуйте Ollama. И разумеется, если у вас не зверь-машина, то все модели будут тупее ChatGPT.
Вообще я поразился, как много уже доступно предобученных моделей для скачивания — тысячи их! Все я пробовать, разумеется, не стал, выборочно посмотрел готовое с интерфейсами.
- Сначала я попробовал LM Studio. У него захламленный и запутанный интерфейс. Кроме того, это закрытое ПО, и нет поддержки для Linux. Однако там без проблем можно скачивать LLM-модели и легко переключаться между ними. Для перебора LLM — сойдет. Я попробовал модель “codellama instruct 7B q4” — пишет плохонький Python-код и предлагает плохие советы по Gradle.
- Затем я попробовал GPT4All. Довольно минималистичный интерфейс, хоть и лагает иногда, есть встроенная функция дообучения на локальных документах. Однако функция скачивания моделей сломана. Я использовал “GPT4All Falcon q4”. Он выдаёт абсолютный бред в ответ на вопросы по Gradle даже когда дообучен на документации, иронично указывая точные страницы из PDF-файла исходных данных.
- После этого я попробовал Ollama. Нет GUI, но с ней меньше всего гемора, ИМХО. Немного неудобен многострочный ввод (решается тройными кавычками). Иногда модель ломается и выдаёт несвязанные данные из-за проблем с парсингом. Увы, я не нашёл простого способа дообучить модель на локальных файлах. Я использовал модель “llama2-uncensored” с ним. Да, вы прочитали правильно, ее можно спросить, как роскомнадзорнуться, например (Я покекал с “Ultimately, the best way to RKN is one that you feel confident will ensure your safety and comfort during the process, with minimal risk of unforeseen consequences or complications”). Думаю, это приемлемая замена для GPT — все равно тупая, но зато без тормозов. Для вопросов по Gradle модель давала плохие ответы, но по крайней мере они содержали полезные части, а не только дичь.
- Наконец, я ознакомился с PrivateGPT. Установка не очень удобная, но и ничего сложного. Тоже нет GUI, но можно дообучать. Я использовал рекомендованную модель “gpt4all-j-v1.3-groovy”, дообученную на документации Gradle. Полный бред в ответ на вопросы по Gradle, еще и цитирует несуществующий текст из руководства.
- Есть еще LLamaGPT, который будет удобнее запустить в докере, но до него руки не дошли.
Теоретически можно загрузить модель Ollama в интерфейс GPT4All и дообучить, но я заленился это делать.
Уведомления от сервера клиенту
На прошлой работе, когда надо было выбрать технологию для отправки уведомлений клиентам, остановились на Centrifugo — довольно классный сервер для отправки сообщений по веб-сокетам (там были свои приколы, но зато было прикольно писать разработчику прямо в личную телегу).
До этого N работ назад использовали Crossbar.io, но когда я писал этот пост, обнаружил, что он уже при смерти.
А еще когда я смотрел альтернативы Centrifugo, то наткнулся на Server-sent Events (aka SSE, aka EventSource). Это стандарт для веба, который позволяет в одностороннем порядке слать уведомления. Рандомную демку можно посмотреть тут, работает даже с curl из коробки. В общем, жду светлые времена, когда в web-стандарте начнут поддерживать докер-контейнеры, чтобы там кубер свой запустить…