duck-typing sh..

t:([] k:`a`b`a; v:1 2 3)
select k, v, kk:?[1=v mod 2; {`$a,a:string x} each k;k] from t
k  k1 v
-------
aa a  1
b  b  2
aa a  3

select k, v, kk:?[1=v mod 2; {`$a,a:string x} each k;k] from 0#t
'type
  [0]  select k, v, kk:?[1=v mod 2; {`$a,a:string x} each k;k] from 0#t



The root cause problem is quite simple:
type {x} each `a`b
11h
type {x} each `$()
0h // brakes everything, because ?[] check type of second argument

Попытался переехать на linux, и откатился назад.

После прочтения https://www.phoronix.com/scan.php?page=article&item=icelake-clear-windows&num=1, поставил разные линуксы на второй ssd:
из приятного - действительно время сборки с ходу в два раза меньше.
CPU-бенчмарки тоже показали что тут собирается как-то лучше: https://github.com/inv2004/rust_vectors/blob/master/win_lin.md

Однако, того, что при установке пакетов зависает мыша, dd if=1.iso of=/dev/sdb1 вообще даже на kill -9 не реагирует, гном упал один раз, хотя у меня просто lenovo без всяких nvidia. в общем, чисто на уровне ощущений убунта оставила очень неприятные впечатления, зато приятные впечатления оставили elementary-OS и dwm+antiX (хотя наверное стоило бы MX-Linux).

из печального - chromium даже с на странице с простыми баннерами бывает поджирает под 30% CPU, надо постоянно что ли на top смотреть чтобы просто браузером пользоваться? скроллинг заметно хуже, youtube вообще не говорю - под 100% CPU улетают на простых даже видео - т.е. пользоваться всем этим не очень приятно, я-то думал такой проблемы нет, а за 20 лет до сих пор в линуксе нету браузера по сути нормального.

В чате меня спросили, сколько бы я лично пожертвовал на развития десктопа linux'а, я ответил какую-то сумму, но после убунты я решил, что фиг бы я за это стал вообще платить, а лучше бы отдал, чтобы разобрать что же такое притормаживает у меня в винде, и действительно вспомнил, что IDEA что-то там делает с антивирусом - попробовал, и это разогнало сборку cargo, хоть и не до линуксовых значний, но значительно ближе.

Осталось разобраться с этом: https://github.com/inv2004/rust_vectors/blob/master/win_lin.md
Но там код не такой уж сложный - попробую сравнить C++ - вариант.

-- update --
провёл ~ неделю на elemenetary - она даже понравилась, впрочем отличия от разных ubuntu не очень значительные. Открытием стало, что в аpt всё настолько протухшее, что много чего ставить из snap или flatpack, даже neovim.

но окончателточку поставило, что на батарее ноут на одной батарее живёт около 4часов, когда под win более 5 1/2, и то, под lin я старался ничего лишнего не запускать.

Rust - достаточно

Rust практически вылетел из зоны моих интересов, жаль что довольно большой проект на нём застрял.

Ситуация такая: я уже почти увидел свет в конце тоннеля по проекту, но, на клиентской стороне использовать монгу не решился => нужно уметь читать данные как из монги так и из локальных файлов. В качестве такого решения напрашивается некий trait Storage, который реализует функцию создания итератора для структур Mongo и Local (из файла). Итераторы соответственно MongoIterator и LocalIterator которые реализуют просто Iterator. Проще, вроде как, и придумать трудно.

Собственно всё, что Local можно отбросить, чтобы просто сделать MongoIterator - надо в ней хранить и коллекцию и курсор, а это уже получается self-referential структура, после двух недель борьбы с Pin и unsafe (не смотря на то что пример вроде как есть тут: https://doc.rust-lang.org/std/pin/#example-self-referential-struct , но это не очень помогло), знающие люди подсказали поискать в крейтах, и действительно, нашёлся некий https://crates.io/crates/rental , который естественно полон макросов, а куда в расте без них, которые генерят это self-ref с лайфтаймами друг на друге и функции для их извлечения.

Кое-как всё пройдено, сам крейт проекта нормально собирается, теперь надо просто использовать это в бинарнике - и тут хоп - эта вот штука ещё используется, хотя вот тут уже конец блока, чуть ли не в main, с какой такой стати, почему - не ясно вообще, у меня уже начали опускаться руки, попытки понять лайфтаймов макросов, генерящих Pin, не сильно обрадовали и я пошёл искать тех самых знающих людей, которых мне помогут. Люди, как мне кажется, действительно знающие, нашлись и даже принялись за проблему, починили за час ... но нет, я просто случайно закомментил весь значимый код, раскомментил, и люди пришли к выводу, что разобраться в чём дело не удаётся. А это по сути просто интерфейс Storage - проще, мне кажется, и придумать нельзя.

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

--- update ---
через три дня, мне постучались в телегу, и сказали, что не спали три ночи, но проблему исправили - ура.

windows terminal

неплохо. меня раньше от PS отгораживало, что он грузится дольше cmd или conemu+clink, в windows terminal всё быстро + после накидки привычных биндингов + полупрозрачности фона - вообще удобно стало, хотя, конечно PS пока не очень привычен.

Да и по ущущениям быстрее conemu работает.

Rust - опять #2

Для предыдущей проблемы пришлось патчить hyper. Справился - отлично, можно идти дальше, пару новых строчек кода (безопасного) и программа _после компиляции_ кидает ошибку на 15 страниц. В чём дело? Вероятно, простая и безопасная библиотка по выводу progress-bar'а на экран запуталась в своих безопасных Mutex'ах в самом безопасном на свете языке.

Rust - опять

Есть у меня pet-проект, который тянется уже больше года и, постепенно, подходит к финальному аккорду.

В какой-то момент было решено изменить способ хранения данных у клиента на простые файлы => понадобилась некая скачивался данных из базы для этого, всё работало почти отлично - данные качались чанк за чанком, прогрес-бар показывал сколько осталось. Кроме одного - данные не сжаты и их много - отдавать потоком - остаться без Content-Length - пользователь будет в неведении сколько осталось. Сжимать сразу много - пользователю очень долго ждать этого Content-Length.

Было решено просто - собирать по 1000, сжимать и отдавать - всё опять же работало, но что-то было странно - иногда некоторые чанки приходили битыми. Посмотрев на пакеты стало понятно - что пакеты нормальные, а вот способ их обработки у hyper такой - если chunk не влезает в буффер (8kb) - то выдавать chunk с тем что есть, а остальное - как будто это другой чанк. Насколько это корректное поведение не берусь судить, возможно и верное. Хотел было переехать на web-sockets, и тут, actix-web, казавшийся нормальным в качестве http показал, что структура для ws должна делаться так: Client<SinkWrite<Message, SplitSink<Framed<T, Codec>, Message>>> - просто же, и удобно - все кишки видны, а то мало ли нужно будет из client.0.0.0 извлечь codec.

Дальше надо описать актор, потом Handler, потом ещё StreamHandler, в который надо передать mut-контекст этого клиента, после чего из него дёргать руками методы типа ctx.0.write или обёртки. Но это не заработает со фьючовыми стримами, потому как при создании этого клиента - надо вызвать мутабельный add_stream на нём, в котором связать Stream и контекст - видимо иначе он не будет знать что надо дёргать этот handler, при этом, даже если совершить все эти действия - это только для обработки выходного потока из stream - как писать в него из другого стрима без своего impl Stream поверх - останется загадкой.

В общем, от такого юзать ws как-то расхотелось. Знающие люди говорили, что надо просто накрутить length_delimited кодек на чанки http и у меня будут нормальные фреймы данных - попробую в эту сторону. Кодеки работают через ASyncRead, а hyper/actix выдают Stream<Item=Vec<u8>> - хотя в общем-то понятно, что результат их работы в этом случае одинаков, и только в futures 0.3 сделали метод into_async_read() который позволяет одну абстракцию преобразовывать в другую => можно просто писать в codec - ура!, но нет, не ура, tokio 0.2 почему-то имеет свои ASyncRead, которые почему-то не совместимы с futures 0.3, а другие мне не подойдут. Есть некий клей - compat, но, бывалые люди, сказали что всё же _надёжнее разобрать байты руками_, чем пробраться через страницу какой-нибудь ошибки, которую покажет что compat(), без compat() ошибки и так по пол-страницы и не сильно проще читать.

Вернёмся к тому, что я никак не ожидал - что я могу застрять на несколько недель на простой скачивалке файла чанками, a раст, в очередной раз, как говорится, пробивает дно в производительности сроков написания чего-то отличного от примеров из папки examples (кстати и это часто не собирается). И у меня много таких случаев о которых можно было бы рассказать не меньше - но первый раз, когда решил написать.

Rust, рефакторинг

Всё работало, вроде неплохо, пока не подключил extern crate pyo3. Естественно всё просто в Rust быть не может - не могу обернуть структуру с лайфтаймами макросами pyo3 => начался глобальный рефакториг по вычищению от лайфтаймов довольно центральной структуры => всё замазывается толстым слоем Rc/Arc/RefCell, настолько толстым, что хотется начать писать на Swift.

что-то типа такого:
self.borrow().control.borrow().stats.borrow_mut().counter += 1;


какой приятный код :(
При этом это по сути убивает всю lifetime концепцию - так как каждый borrow - это твой личный и ручной контроль поверх раста.

teamviewer => anydesk

teamviewer меня заблокировал якобы за коммерческое использования, хотя всё что я сделал - поменял полиси телеметрии на компе. В ответ на запрос вернуть всё назад они ответели что не видят для этого причин, но если очень надо, то я должен выслать расписку, паспорта и фотографии, что не то что сложно, но как-то немного противно.

Переехал на anydesk:
- удивительно, но по локалке он намного быстрее.
- интерфейс немного более багованный - иногда на полном экране артефакты.
- мобильное приложение тоже не очень удобное.

teamviewer и screenconnect

Однозначно побеждает первый - когда я соединяюсь между компьютерами в одной сети - то можно даже youtube нормально смотреть. screenconnect гораздо медленнее, и похоже не умееть напрямую соединяться.

ubuntu => alpine linux => ubuntu

Думал, о том, что ubuntu немного жирновата, посмотрел вокруг и наткнулся на alpine в образах scaleway, тут же поднял сервер. По-началу действительно немного меньше, но как только начинаешь всё ставить - то оно быстро вырастает до почти убунтувских размеров.

Собрал всё под неё, посмотрел на глаз сколько жрёт процессора - на глаз меньше прилично, смотрю дальше, ба! , да оказывается другой проц на scaleway поднялся. Поднял ещё одну убунту - замерял - alpine кажется немного больше жрёт cpu на той же задаче (я конечно понимаю точность сравнения top'ом :) ). Из приятного - всё кажется более простым и арчеподобным, пакеты аналогично - mongodb и rust из коробки довольно свежие. Пока не наткнулся на это: http://www.etalabs.net/compare_libcs.html , а потом ещё какие-то косяки с безопастностью и с производительностью тоже (причём свежие) нагуглились, ну и ну его решил, - опять убунту на scaleway поднял.