Бурундук-зануда ноет на Луну


Гео и язык канала: не указан, не указан
Категория: не указана


https://vk.com/wall-61226939_4054
Небольшие заметки о том, как несовершенен этот мир.
Обратная связь: https://t.me/burunduk3

Связанные каналы

Гео и язык канала
не указан, не указан
Категория
не указана
Статистика
Фильтр публикаций


Коллеги зовут хайкать.
@
Четыре часа ходишь пешком по горам.
@
Гугл присылает пуш (см. рисунок) и спрашивает, как мне подъёмник.

Отличный подъёмник, с тропы вообще шикарно смотрится! Пять из пяти!


Рисунок.


Когда (почти лет 15 назад уже) у меня появился первый ноутбук, я обратил внимание на маленький рычажок для определения, открыта ли крышка. Если её начать закрывать, то крышка заденет рычажок, он нажмётся, и внутри сгенерируется событие «крышка закрыта». Просто и удобно, как лампочка в холодильнике.

Но, лишняя движущаяся деталь — это не очень хорошо. Она ненадёжна, она может сломаться, в результате в современных ноутбуках ставят магнитные датчики. Никаких внешних деталей, очень удобно.

Особенно удобно когда ставишь ноутбук на другой ноутбук, и первый уходит спать. Потому что, видите ли, от в крышке другого ноутбука точно такой же магнит, почему бы датчику и не сработать.


Про телефонные номера

tl/dr
: Не требуйте номер телефона от людей, особенно если вы сайт в интернете.

Я помню, как мобильный телефон перестал быть экзотической игрушкой для богачей и стал появляться у обычных людей. Я помню, как он сделал бесполезными «домашние» стационарные телефоны. Я помню, как менялись их возможности — от змейки на древней Нокии до нынешнего разнообразия приложений и применений, которое ограничивается в основном монополией производителей двух операционных систем. Я помню, как мобильные телефоны научились ходить в интернет, и почти сразу же его раздавать — через ИК-порт, через специальный кабель, через bluetooth, и наконец просто подняв wifi-точку. Я даже помню «3g-модемы» в виде отдельных устройств, которые можно было воткнуть в usb-порт.

Лет десять назад это привело к тому, что мобильный телефон был практически у каждого. А в телефоне — сим-карта от какого-нибудь мобильного оператора, и привязанный к ней номер. И это «у каждого» оказалось провокацией на весьма существенную ошибку. Ошибку — потому что «у каждого сейчас», даже если это и было так, не означает «у каждого, и так будет всегда».

Я говорю о том, что многие сервисы (сайты, социальные сети, …) стали использовать номер мобильного телефона в лучшем случае в качестве обязательного фактора аутентификации, в худшем — для идентификации. Банки присылают sms с кодами подтверждения транзакций, ВКонтакте привязыет намертво телефон к странице, Телеграм вообще считает, что номер телефона — это и есть пользователь. Да даже простое приложение для аренды самокатов в Мюнхене первым же экраном требует ввести этот чортов номер. Чуть лучше делает, например, гугл: там телефон может быть вторым фактором аутентификации, но его можно убрать и использовать только другие варианты.

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

У меня сейчас есть телефон. В нём симка от какого-то немецкого оператора, с ней ассоциирован номер, но я его не знаю. Симка, кстати, не моя. Мне от мобильного телефона нужен только интернет: sms-общение с живыми людьми давно кануло в Лету, голосовая связь перешла в скайпы, зумы и прочие гуглмиты. Да даже в вышеупомянутом Телеграме есть голосовые звонки, для тех кто почему-то хочет напрягать связки чтобы передать какую-нибудь мысль.

Вполне возможно, что завтра у меня будет другая симка, с другим номером, от другого оператора. Забуду положить денег на счёт, куплю новую, вроде не проблема, если новый доступ в интернет будет — то и хорошо. Ещё у меня есть старая симка от Мегафона, от которой я очень хочу избавиться. Но не могу, потому что чортов ВКонтакте и чортов Телеграм даже если позволяют сменить номер телефона, не позволяют убрать его на хрен.

Конечно, я нерепрезентативен. У кого-то могут быть старшие родственники, до сих пор не освоившие Телеграм, кто-то может часто созваниваться по деловым вопросам (какой-нибудь условной доставке даже я могу сказать номер телефона, которые привязан к симке, что у меня прямо сейчас — если им что-нибудь от меня понадобится сегодня–завтра, то у них есть шанс). У кого-то могут быть ещё какие-нибудь причины ассоциироваться с номером, как в известной антиутопии. Но эпоха, когда номер можно было потребовать от каждого, и рассчитывать это этот номер будет с человеком ещё много лет, безусловно прошла.

Ставь 👌 если тоже хочешь, чтобы номера телефонов остались лишь историей, 📱 если в 2020-м у каждого приличного человека должен быть номер телефона (а я тут ерунду какую-то мелю), ☎️ если ничего не понял (и регулярно крутишь ручку три раза со словами «алло, барышня, соедините меня с …»).


Уверен, многие слышали про запрещённые простые числа — цензура и копирайт-фашисты любят «запрещать» какую-нибудь информацию (или её распространение), информация выражается числом, числа бывают простые. Какое вы знаете минимальное запрещённое простое число? Я, вот, например, недавно услышал, что 709 (да, оно простое) считается запрещённым в Китае.


Обсуждение в одном чатике спровоцировало меня взять черновик, которые лежит ещё с прошлого лета, да всё лапы не доходили допилить и опубликовать. Извините, получилось длинновато.

Ещё рассказывают, что «асинхронность» — термин как раз для извращений с полупотоками, а простую и эффективную кооперацию называют «неблокирующей». Впрочем, и на счёт этого названия я как-то сомневаюсь.


Корутинные будни, часть 3 из 3.

Callback hell

Один из способов — вынести часть «после» в отдельную функцию и вместо обычного recv () вызывать умную обёртку, мол, «мне нужны данные, когда они появятся — вызови вот этот метод». Если у вас была локальная переменная — извините, теперь ей место в поле вашего класса, или в замыкании вашей функции (для тех, кто уже умеет в лямбды). В целом, работающий подход, если кто писал на node.js до ES-2015, то там только так и жили. Вот только код разрастается в неприятную сторону, когда цепочка колбеков становится длиннее пяти.

Но мы же не роботы, чтобы вкалывать. Давайте попросим компилятор (он железный, ему всё равно) расщеплять нашу функцию на кусочки, которые можно будет выполнять по одному и ждать данных в промежутках. Это и называется корутины. Они суть просьба для компилятора:
— сделать специальный корутинный объект,
— хранить в этом объекте точку выполнения корутины,
— хранить в этом объекте то, что кажется локальными переменными,
— от этого объекта нужно только действие «выполнись-ка до следующей асинхронной точки», ну и часто любят какое-нибудь взаимодействие на это завязать (yield данных туда-сюда, например).


Вместо заключения

Потоки иногда тоже нужны. Например, потому что в современных операционных системах можно мультиплексировать обращения к сети и всякий IPC (pipes, signals), но не обращения к файловой системе. Попытка сделать`read ()` из обычного файла заблокирует ваш поток, возможно надолго (например, если файловая система — sshfs, а у нас сеть закончилась). Такое можно и нужно выносить в отдельный поток, а лучше пул потоков. Аналогично, бывает пачка вычислений, независимая от основного выполнения — чтобы воспользоваться преимуществом многоядерных процессоров и многопроцессорных систем, понадобятся потоки для разгрузки вычислений на основном.

Но для понимания асинхронного подхода и корутинок лучше забыть про параллельные вычисления. Они тут только мешают. Чтобы обрабатывать десять тысяч подключений одновременно, достаточно последовательных, и очень простых — если не давать себя запутать.


Корутинные будни, часть 2 из 3.

Вытесняющая и кооперативная многозадачность

Лет 30 уже все неспециализированные операционные системы — многозадачные. Что на сервере, что на телефоне, это платформы чтобы можно было запустить прорву разного софта, и он там крутился — грел воздух, разряжал батарею, иногда случайно делал что-нибудь полезное. А операционная система следит, кому какие данные пришли, и распихивает процессы по ядрам. Если кто-то засел за вычислениями, а новых данных не просит, его могут принудительно поставить на паузу, если вдруг кому другому надо повычисляться. Это называется вытесняющей многозадачностью: тебе дадут процессор, но если ты повис в своих циклах, или в блокирующем ожидании данных — тебя могут вытеснить и дать процессор другому.

Внутри, скажем, веб-сервера, дела обстоят немного иначе. Там одна программа (специально не говорю «один процесс», а то всякое бывает), но много источников данных. Это может быть уже существующий клиент, которые послал ещё байтик своего запроса, может быть новый клиент, желающий соединения, могут быть данные «с обратной стороны» — скажем, если мы хотим сгенерировать страничку, для этого послали запрос к базе данных, и вот получили ответ.

Как делают хорошие веб-серверы: хранят какую-нибудь структурку данных для клиента. На каждое приходящее событие понимают, к какому клиенту это относится, быстро что-нибудь меняют в соответствующей структуре, ждут следующего события (которое может иметь отношение к другому клиенту, ну и что). Несколько процессов/потоков для таких порой имеет смысл, но не определяющий. Это называется кооперативной многозадачностью: внутри сервера обрабатывается много клиентов, но они не спорят за вычислительные ресурсы, а отдают друг другу место, когда заканчивают свои дела. Зато если обработка какого-то клиента внезапно займёт много времени, ждать придётся и остальным тоже.


Костыли и принцип чайника

Как делают плохие серверы: на каждого пришедшего клиента просят операционную систему создать поток/процесс, и в этом процессе работают только с тем клиентом. Почему это плохо?
Это очень сложная архитектура. На любую мелочь (начиная со статистики — хотя бы счётчика запросов), которая нужна всем клиентам, приходится городить синхронизирующие примитивы. Добро пожаловать в мир мьютексов, блокировок, атомарных операций, барьеров памяти и просранных кеш-линий.
Это очень неэффективно. Каждый поток требует структуры данных для его состояния, записи в недрах ядра, выделенный стек, а переключение между потоками занимает много времени и снова куда-то делся весь кеш.

Почему же тогда много софта (особенно старого — mysql плодит по потоку на клиента, apache по процессу) всё ещё сидит на этом кактусе? Потому что многопроцессорность/многопоточность — уже существующие решения, и их сложности — привычные сложности для старшего поколения. Даже если асинхронный подход проще и эффективнее, в нём всё равно надо разбираться.


Асинх-что?

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

Сложность ровно в том, что это «получить ещё данных» на самом деле — ждать, пока придут данные, если пришли — продолжить, а если пришли чьи-то другие — продолжить другую задачу, а потом ждать дальше. Такие фокусы один маленький recv () делать не умеет, придётся изобретать что-то похитрее.

В простых случаях можно отделить сбор данных от вычислений: скажем, байтики из сети собирать в буфер, а когда там накопится запрос целиком — уже обработать как полагается. Так, например, работают (по крайней мере, работали когда-то) кошачьи движки (KittenDB), на которых крутится VK и Telegram. В более общем случае, когда мы хотим данных, надо как-то разорвать исполнение на «до» и «после».


Корутинные будни, часть 1 из 3.

Читая, что там у c++ с корутинами, занесло меня на некий сайт (из гугла по запросу «c++ coroutines example» или какому-то такому). Читаю, и какое-то смутное чувство терзает всё время, как будто что-то не так.

А, точно. В статье постоянно (даже на картинках) сравнивают корутины (и их друзей, например, fibers) с потоками. Хотя, казалось бы, при чём тут.

Потоки — весьма полезная штука сама по себе. Но к асинхронному программированию они не имеют отношения примерно никакого. Конечно, их можно использовать как сложный и дико неэффективный способ мультиплексировать ввод/вывод, который будет работать в программах уровня школьных поделок. Если вам хочется порешать головоломки с мьютексами — пожалуйста, но когда нужно что-то работающее — пожалуйста, нет.

Впрочем, обо всём по порядку. А значит, надо начать с путешествия в прошлое.


Исторический экскурс

Все помнят старый анекдот про «папа, а что такое многозадачность? — сейчас дискетку доформатирую и покажу». Давным давно компьютеры (англ. computer — вычислитель) позиционировались как устройства, позволяющие решить какую-нибудь информационную задачу. В парадигме «прочитать данные, произвести вычисления, вывести результат». Революционный подход по тем временам. Вопрос к аудитории: какие именно вычисления производит (читает данные, выводит результат) программа, запущенная на телефоне у школьника, который на скучной лекции запускает птиц в свиней?

В детстве мне попадались то ли книжки, то ли ещё что-то, объясняющее, почему многозадачные системы (а не всякий там DOS, который я одним глазом ещё застал) — шаг в будущее. Там рисовалась картинка-график, что делает программа, ждёт ли ввод/вывод, или реально что-то считает. Две «типичные» программы, которые жрали CPU только половину своего времени (случайно раскиданными блоками), ускорялись в полтора раза, если научить процессор выполнять вторую, когда первая ждёт I/O. Ура, программы работают быстрее, выше, сильнее, так доберёмся до звёзд.

Теперь давайте предствавим реальную типичную программу, уже более современную. Например, браузер, текстовый редактор, или командную оболочку в терминале. Вычислениями оно занимается, гм, примерно никогда. Подавляющую часть времени ждёт команды от пользователя, или в лучшем случае (современные браузеры с современными сайтами и всякими автообновлениями) — данных из сети. Программы, жрущие CPU как не в себя, существуют, некоторые даже занимаются этим по делу (а не майнят койны или компенсируют некомпетентность своих авторов). Погрепать какой-нибудь большой файл, перекодировать видео, посеквенировать какой-нибудь геном — важные задачи, но не самые популярные.

Поэтому я часто предпочитаю другую парадигму: ждать, пока что-нибудь произойдёт, быстро реагировать, ждать дальше. Если вы веб-сервер, то «что-нибудь» может быть, например, запросом от клиента, если вы редактор — командой от пользователя.


Мне не очень интересно мнение большинства, но любопытно.

Расскажите, про ваше отношение к utf16.

👍 Сам пользуюсь, всем рекомендую.
👌 Хороший баланс между utf8 и utf32.
👎 Не нужен, и вообще неплохо бы его отправить на свалку истории, где-то между utf7 и cp1251.
🖕 Кто вообще его придумал, такая груда костылей не должна была появиться.
❔ О чем вообще речь.


См. рисунок 2.

Это мне дали потыкать потыкать современный линукс (вроде бы Arch). В данный момент он безуспешно пытается выключиться — обратите внимание на сообщение про «stop job is running». Что же ему мешает?

Да ничего особенного, просто пара процессов зависла в системных вызовах. Тяжёлое детство, кривые ядра, баги бывают у всех, тут вот так. Напомню, что если процесс завис в ядре, то никакой kill -9 ему уже не поможет.

Вот только я не понимаю, зачем это ожидание в три с половиной минуты, и в процессе выключения оно делается минимум дважды (для одних и тех же процессов). Скрипты, видимо, посылают SIGTERM, ждут какое-то время, потом посылают SIGKILL, … и вот тут я теряюсь. Тот, кто это придумал, он рассчитывал, что за эти три с половиной минуты произойдёт что? Прилетит Санта-Клаус с Марса и починит ядро, что ли?


Рисунок 2


См. рисунок 1.

Это — формочка для заказа на каком-то интернет-магазине (кажется, это была икея). Обратите внимание на сумму: €119.44 + €39.00 = €11983.00. (Знакомый запах, не правда ли, любители языков, где "1" + "2" будет 12?)

Как же так получилось? А дело в том, что страничка автопереведена в браузере. Что, само по себе, не должно быть проблемой, но в двух местах потрудились программисты — как обычно, без применения интеллекта.

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

Второе: авторы хрома, которые впаяли этот перевод так, что у джаваскрипта есть доступ к частично переведённому тексту. (По идее, джаваскрипт вообще не должен знать, что сайт перевели, разве нет?)

Ну и в качестве связующего раствора — всеми любимая локаль. Обратите внимание, что 119.44 указано с точкой в качестве разделителя, а 39,00 — с запятой. Я не знаю, как и зачем при переводе умудрились это поменять. И я не знаю, как можно было в джаваскрипте взять значение из элемента на странице, а не хранить его вещественным числом в настоящей переменной.


Рисунок 1


О пользе школьного образования.

Кто-то там ругался, что абстрактный учитель литературы видит глубинный смысл, хотя автор просто пишет что занавески были синие. И ещё требует от учеников чтобы они умели этот скрытый смысл угадывать. Вечный вопрос: что хотел сказать автор?

Прошло больше дюжины лет. Читаю код, смотрю в историю коммитов. Код в большом opensource-репозитории, закоммиченный несколько лет назад, проверяет указатель profile_ на nullptr, и даже какую-то логику на эту тему делает. При этом profile_ никогда не должен быть пустым, и никогда не оказывается. Что, чорт побери, этим хотел сказать автор?!


Какой милый баг.

Вкратце: обычно адреса PCI-устройств записывают в шестнадцатеричном виде (например, на 00:1f.3 у меня живёт звуковая карта), но Xorg выпендрелся и принимает в десятичном. И никто этого не замечал, потому что обычно видеокарта живёт на «маленьких» числах, вроде 03:02.0.

Отдельные лучи любви тем, кто придумал падать с ошибкой на эту тему до того, как открыть лог-файл. Так что мне как обычно пришлось расчехлять strace, и уже по ошибке оттуда найти вышеупомянутый вопрос (с ответом, за что спасибо).


Сегодня будет рассказ про M.2.

Это такой новый (появился в 2013-м году) формат карточек для компов — как всяких wifi, так и небольших SSD.

Что же с ним не так, спросит пытливый читатель? Отвечу, что он не совместим. Ну и что, это же типично для новых форматов, быть несовместимыми со старыми?

M.2 не совместим не только со старыми, M.2 несовместим сам по себе. У него различаются:
— Разьёмы, механически. Там предполагается вырез, и мест этого выреза есть с полдюжины вариантов. Популярных, правда, всего два (B и M) для сокета и три (B, M, универсальный B/M) для карточки.
— Форм-фактор карточки. Если у тебя SSD 2280, а в ноутбуке места только под 2242 — извини. Разве что лобзиком подпилишь не влезающие гигабайты.
— Интерфейс. Если карточка влезла по остальным параметрам, это ещё ничего не значит. Может быть разъём, поддерживающий только AHCI, а может быть — только NVMe.

Возможно, что-то я забыл, но сколько уже открывается различных комбинаций!

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


Часовые пояса — известная головная боль (чёртова планета, почему она вертящийся шар, а не плоский блин). Особенно если работаешь в глобальной компании. Ладно бы ещё временные метки у постов, писем, комментариев — иногда автоматически переводятся во что-то понятное.

Но порой люди сами пишут, например, «отвечу завтра утром». И сиди, понимай, когда у него утро. Впрочем, мои коллеги как правило классные и уточняют: «отвечу завтра утром в 9am CST». Вот теперь всё понятно, осталось только глянуть, что такое CST.

Как нам подсказывают, эта аббревиатура может означать:
— Central Standard Time, UTC-6
— China Standard Time, UTC+8
— Cuba Standard Time, UTC-4

Превосходно. Изумительно. Просто одно стандартнее другого.


Всем известна одна из современных болезней интернета: сбор статистики. На каждой захолустной страничке найдётся хорошо если всего полдюжины разных счётчиков. Когда пользователь Alice заходит на сайт bob.example.com, то об это сразу узнают Гугл, Яндекс, и все прочие чаки, которые занимаюся этим сбором информации в сети.

Ладно бы просто собирали — в конце концов, если автор сайта хочет палить каждого, кто к нему заходит, как тут ему помешать¹. Так этот отстой ещё и ресурсы пользователя жрёт: скрипт загрузи, данные собери, запрос отправь — трафик, процессор, память не резиновые. Порой доходит до того, что сайт не отображается, пока висит запрос на загрузку какого-нибудь шпионского скрипта или рекламного блока.

Лечение тоже в целом все знают: самое простое — топка локалоста. Записать в /etc/hosts строчку с провинившимся доменом (вроде mc.yandex.ru или www.google-analytics.com) на несуществующий адрес, и дело с концом. Кстати, давайте делиться своими топками.

Это работает пока какой-нибудь криворукий веб-разработчик не решит пострелять по ногам своих пользователей. Так, например, на сайте Аэрофлота без метрики отваливается поиск, потому что, видите ли, Uncaught ReferenceError: yaCounter12084547 is not defined. Они вообще сами пробовали этим пользоваться? Полететь, что ли, Люфтганзой, раз эти не хотят мне билеты продавать…

¹ Помешать, конечно, можно — заходя на сайт, не палить себя этому сайту, как это делается в сетях tor и i2p.


Время поиграть в динозаврика.

Показано 20 последних публикаций.

194

подписчиков
Статистика канала