Pull to refresh
1748
4

Переводчик-фрилансер

Send message

Если вы собираетесь сидеть и ничего не делать, то хотя бы делайте это правильно

Level of difficultyEasy
Reading time4 min
Views4K

Иногда бывает нужно, чтобы API не делал ничего. При этом важно, чтобы он не делал ничего правильным образом.

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

Неправильно было бы, если бы функции печати выбрасывали Not­Supported­Exception. Установленное пользователем на Xbox приложение, вероятно, в основном (если не исключительно) тестировалось на PC, где печать всегда доступна. При запуске на Xbox исключение, скорее всего, не будет обработано, и приложение вылетит. Но даже если приложение попытается перехватить исключение, то, вероятно, отобразит сообщение типа «Ой. Что-то пошло не так. Обратитесь в службу поддержки и сообщите ей вот этот код ошибки».

Гораздо лучший способ «поддержки» печати на Xbox — это успешное выполнение функций печати с сообщением о том, что принтеры не установлены. При таком поведении в случае попытки печати приложение попросит пользователя выбрать принтер и отобразит пустой список. Пользователь осознает, что принтеров нет, и отменит запрос на печать.

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

Смысл здесь в том, чтобы все функции печати вели себя так, чтобы поддержка печати полностью поддерживалась, но принтеры постоянно загадочным образом отсутствовали.

Читать далее
Total votes 17: ↑15 and ↓2+13
Comments8

Тёмные паттерны UX себя не оправдывают

Level of difficultyEasy
Reading time3 min
Views4.3K

У меня было хорошее настроение: я опубликовал свою статью об RSS, и она оказалась довольно популярной.

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

Я нажал на крестик в правом верхнем углу рекламного блока. И именно тогда всё пошло не так.

Вместо того, чтобы закрыть рекламу, Feedly показал мне всплывающее окно, сообщающее, что единственный способ удаления «этого модуля» (читай: рекламы) — «напрямую поддержать Feedly, купив Feedly Pro».

Повторюсь, я не против, что Feedly показывает рекламу бесплатным пользователям, но неработающая кнопка закрытия — это тёмный UX. Я почувствовал себя обманутым: я не буду платить за ваш сервис, я не буду нажимать на рекламу.

Читать далее
Total votes 17: ↑15 and ↓2+13
Comments8

Как языковая модель предсказывает следующий токен (часть 1)

Reading time27 min
Views6.5K

Я обучил небольшой (порядка 10 миллионов параметров) трансформер по превосходному туториалу Let’s build GPT: from scratch, in code, spelled out Андрея Карпати. После того, как он заработал, я захотел максимально глубоко понять, как он устроен внутри и как создаёт свои результаты.

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

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

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

Читать далее
Total votes 27: ↑27 and ↓0+27
Comments5

Почему OKR — это отстой

Level of difficultyEasy
Reading time7 min
Views23K

Наверно, многие из моих читателей как раз закончили квартальный (и/или годовой) цикл планирования, так что сейчас будет подходящее время напомнить, что процесс, которым мы пользуемся как стандартом в технологической отрасли, на самом деле — полная чушь. Разумеется, я имею в виду методологию Objectives and Key Results. Давайте же поговорим об OKR, что это такое и откуда они взялись, а ещё о том, почему это ужасная идея.

Читать далее
Total votes 59: ↑53 and ↓6+47
Comments26

Поисковый движок в 80 строках Python

Reading time11 min
Views11K

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

Давайте поговорим о целях. Слышали когда-нибудь о «кризисе сложности обнаружения маленьких веб-сайтов»? Проблема в том. что маленькие веб-сайты наподобие моего невозможно найти при помощи Google или любого другого поискового движка. Какова же моя миссия? Сделать эти крошечные веб-сайты снова великими. Я верю в возвращение славы этих малышей вдали от SEO-безумия Google.

В этом посте я подробно расскажу о процессе создания поискового движка с нуля на Python. Как обычно, весь написанный мной код можно найти в моём GitHub (репозиторий microsearch). Эта реализация не будет притворяться готовым к продакшену поисковым движком, это лишь полезный пример, демонстрирующий внутреннюю работу поискового движка.

Кроме того, мне стоит признаться, что в заголовке поста я слегка преувеличил. Да, поисковый движок действительно реализован примерно в 80 строках Python, но я ещё и писал вспомогательный код (краулер данных, API, HTML-шаблоны и так далее), из-за которого весь проект становится немного больше. Однако я считаю, что интересная часть проекта находится в поисковом движке, который состоит из менее чем 80 строк.

P.S. Написав этот пост и microsearch, я осознал, что пару лет назад нечто похожее написал Барт де Гёде. Моя реализация очень похожа на работу Барта, но я считаю что кое-что улучшил, в частности: (1) мой краулер асинхронный, что сильно ускоряет работу, (2) я реализовал пользовательский интерфейс, позволяющий взаимодействовать с поисковым движком.

Читать далее
Total votes 29: ↑29 and ↓0+29
Comments4

Как я уменьшил размер образа docker на 40%

Level of difficultyEasy
Reading time16 min
Views15K

Ежедневно по работе я сталкиваюсь с Dockerfile, написал несколько из них самостоятельно, создавал контейнеры и всё такое. Но я никогда не публиковал их в реестре docker hub. Мне хотелось создать ugit — инструмент для отмены команд git (написанный в виде шелл-скрипта), который бы могли использовать люди, не любящие устанавливать случайные шелл-скрипты из Интернета.

Да-да, знаю. НАДО ПЕРЕПИСАТЬ ЕГО НА GO/RUST/ЕЩЁ КАКОМ-ТО ВОЛШЕБНОМ ЯЗЫКЕ. Сейчас скрипт состоит из пятисот с лишним строк Bash, поэтому я перепишу его на другой язык только под страхом смертной казни. Кроме того в ugit уже есть практически все функции (осталось реализовать отмену лишь небольшого количества команд, используемых не так часто).

В этой статье я расскажу о том, как написал официальный Dockerfile для ugit (шелл-скрипта) и снизил размер образа почти на 40% (с 31,4 МБ до 17,6 МБ), выполняя пошаговые попытки работы по инструкции. Надеюсь, это замотивирует других любителей шелла тоже публиковать свои скрипты в виде образов docker!

Читать далее
Total votes 23: ↑22 and ↓1+21
Comments50

Как устроена страничная организация памяти x86_64

Level of difficultyEasy
Reading time15 min
Views8.3K

В этом посте я буду говорить о страничной организации только в контексте PML4 (Page Map Level 4), потому что на данный момент это доминирующая схема страничной организации x86_64 и, вероятно, останется таковой какое-то время.

Окружение

Это необязательно, но я рекомендую подготовить систему для отладки ядра Linux с QEMU + gdb. Если вы никогда этого не делали, то попробуйте такой репозиторий: easylkb (сам я им никогда не пользовался, но слышал о нём много хорошего), а если не хотите настраивать окружение самостоятельно, то подойдёт режим практики в любом из заданий по Kernel Security на pwn.college (вам нужно знать команды vm connect и vm debug).

Я рекомендую вам так поступить, потому что считаю, что самостоятельное выполнение команд вместе со мной и возможность просмотра страниц (page walk) на основании увиденного в gdb — хорошая проверка понимания.

Читать далее
Total votes 53: ↑53 and ↓0+53
Comments0

HTML: плохие стороны

Level of difficultyEasy
Reading time12 min
Views4.2K

Вероятно, вы слышали заявления типа «HTML и так по умолчанию обладает accessibility» или «Не нужно изобретать заново этот абсолютно идеальный элемент управления HTML». Я считаю, что это общие заявления, а не универсальные истины. Веб-разработчикам крайне важно осознавать недостатки платформы, поэтому я решил собрать несколько примеров того, когда у HTML возникают трудности как с точки зрения accessibility, так и usability.

Это неполный список и он не включает в себя недостатки ARIA. Мне хотелось найти баланс между широко известными проблемами и чаще встречаемыми (но менее известными), а также добавить в список то, что мы воспринимаем, как должное. В каждом из разделов я укажу степень серьёзности проблемы, альтернативные решения и ссылки, по которым можно найти более подробную информацию.

Читать далее
Total votes 16: ↑15 and ↓1+14
Comments16

Призыв писать компактное ПО, версия 2024 года (с примером кода)

Level of difficultyEasy
Reading time11 min
Views34K

Этот пост посвящён памяти Никлауса Вирта, первопроходца в сфере вычислительных наук, ушедшего от нас 1 января этого года. В 1995 году он написал важную статью A Plea for Lean Software, и в своём посте я постараюсь воспроизвести её почти тридцать лет спустя, с учётом современных кошмаров разработки ПО.

Очень короткая версия поста: современные способы разработки/сборки ПО смехотворны, они приводят к созданию пакетов на 350 МБ для рисования графиков, а простые продукты импортируют 1600 зависимостей неизвестного происхождения. Уровень безопасности ПО ужасен, ведь он зависит и от качества кода, и от его объёма. Многие из нас понимают, что ситуация нерациональна. К сожалению, многие программисты (и их руководство) никогда не работали как-то иначе. А остальным редко выделяют время, чтобы выполнять работу качественно.

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

Надеюсь, этот пост станет моральной поддержкой для страдающих программистов и технологов, стремящихся улучшить ситуацию. Дело не только в вас, и мы не просто страдаем от ностальгии: ПО сегодня действительно очень странное.

Читать далее
Total votes 150: ↑147 and ↓3+144
Comments197

Делаем двоичные файлы Rust меньше по умолчанию

Level of difficultyMedium
Reading time6 min
Views4.8K

Вы когда-нибудь пробовали компилировать program helloworld на Rust в режиме --release? Если да, то видели, какой размер двоичного файла получается? Достаточно сказать, что он не очень маленький. Или, по крайней мере, не был таким до недавнего времени. В этом посте я расскажу, как узнал об этой проблеме и попытался устранить её в Cargo.

Читать далее
Total votes 38: ↑38 and ↓0+38
Comments13

Пишем трассировщик лучей для ZX Spectrum

Level of difficultyEasy
Reading time16 min
Views20K

Я люблю трассировщики лучей и даже посвятил им половину своей книги. Менее известна моя любовь к ZX Spectrum — домашнему компьютеру 1982 года, с которым я вырос и с которого начался мой интерес к графике и программированию. По современным стандартам эта машина столь смехотворно слаба (и даже по стандартам 1980-х), поэтому возникает неизбежный вопрос: в какой степени удастся портировать трассировщик лучей из книги Computer Graphics from Scratch на ZX Spectrum?

В ZX Spectrum установлен процессор Z80 на 3,5 МГц (в тысячу раз медленнее, чем современные компьютеры), который не может умножать числа (!!!), и 48 КБ ОЗУ (в миллион раз меньше); он имеет графический режим 256x176 (примерно в двести раз меньше современного разрешения), способный отображать 15 цветов (в миллион раз меньше, к тому же с довольно необычными особенностями). Интересная машина для графического приложения, активно задействующего CPU!

Я планирую реализовать его на Sinclair BASIC — встроенном языке программирования Spectrum. Это не просто BASIC, а древний, очень ограниченный диалект BASIC. Например, единственные структуры управления в нём — это FOR и IF (а у IF нет ELSE и даже ENDIF); все переменные глобальны; не существует вызовов функций, только GO TO и GO SUB; и так далее. Кроме того, он интерпретируемый, то есть сверхмедленный. Но, по крайней мере, он реализует программное умножение! Если мне нужна будет производительность, то я всегда могу переписать трассировщик на ассемблере.

Я настроил минимально необходимую среду: код на BASIC я пишу в VS Code, компилирую его с помощью BAS2TAP и запускаю в эмуляторе FUSE. Благодаря этому скорость итераций оказалась достаточно высокой.

Читать далее
Total votes 142: ↑141 and ↓1+140
Comments85

Старая ошибка Unix, которую вы можете совершить при сигнале init (PID 1)

Level of difficultyMedium
Reading time2 min
Views3.9K

Init — традиционное имя для программы, которая выполняется как process ID 1, главный наследник всех процессов Unix, исторически отвечающий за управление системой. Process ID 1 настолько критичен для системы, что его или невозможно убить, или система перезапускается при выходе из него (или и то, и другое, тогда этот перезапуск — хак). Сегодня в Linux PID 1 необязательно оказывается двоичным файлом и процессом с именем init в буквальном смысле, в отличие от *BSD, где init остаётся двоичным файлом.

Исторически сложилось так, что по множеству причин системный администратор отправляет сигналы в init, что задокументировано для современных систем Unix, например, на странице руководства к  init(8) FreeBSD. Одна из причин заключается в том, чтобы считывать заново список последовательных портов. Традиционно и даже сегодня это выполнялось отправкой init сигнала SIGHUP.

Программа kill долгое время поддерживала отправку сигналов по имени, но сисадмины ленивы и мы обычно запоминали что SIGHUP — это сигнал 1 (а сигнал 9 — это SIGKILL). Поэтому довольно часто мы вводили kill -1 1 для отправки сигнала 1 (SIGHUP) к process ID 1 (init). Однако эта версия немного опасна, потому что она лишь на один символ отличается от версии с совершенно другими эффектами.

Читать далее
Total votes 26: ↑25 and ↓1+24
Comments2

Сравнение производительности dict() и {} в Python

Level of difficultyMedium
Reading time11 min
Views15K

Какое-то время назад, во время разбора кода, мы обсудили выбор dict() вместо {} в новом коде на Python. Коллега утверждал, что dict() более читаем и чётче выражает цель, поэтому следует предпочесть его. Меня это не убедило, но в тот момент контраргуентов не нашлось, поэтому я воздержался.

Это заставило меня задуматься: в чём разница между типом dict и литеральным выражением {}?

Давайте изучим этот вопрос.

Читать далее
Total votes 26: ↑23 and ↓3+20
Comments19

Почему текст в нижнем регистре сжимается лучше

Level of difficultyEasy
Reading time7 min
Views11K

Буквы в нижнем и верхнем регистре содержат одинаковое количество данных — по 1 байту каждая.

Поэтому удивительно, что замена заглавных букв на строчные снижает объём данных.

Пример: я взял главную страницу Hacker News и переписал заголовок каждой статьи, капитализировав только первые буквы в предложениях (sentence case) вместо первых букв во всех словах (title case). Это позволило мне снизить размер на 31 байт.

Sentence case: The cat sat on the mat

Title case: The Cat Sat on the Mat

Как может замена нескольких заглавных букв на строчные снижать объём? Всё дело в сжатии.

Это непривычно, но если понять, как работает сжатие текста, то начинает казаться логичным.

Читать далее
Total votes 41: ↑32 and ↓9+23
Comments28

Когда Random совсем не случаен

Level of difficultyMedium
Reading time7 min
Views20K

Этот пост — рассказ об истории, случившейся больше десятка лет назад; её код был мной утерян. Поэтому прошу простить меня, если я не вспомню точно все подробности. Кроме того, некоторые подробности упрощены, чтобы от этой статьи могли получить все, кому нравится компьютерная безопасность, а не только любители World of Warcraft (хотя, полагаю, диаграмма Венна этих двух групп сильно пересекается).

Когда мне было примерно 14 лет, я узнал об игре World of Warcraft компании Blizzard Games, и она сразу же меня увлекла. Вскоре после этого я нашёл аддоны, позволявшие модифицировать внешний вид и функциональность интерфейса игры. Однако не все скачанные мной аддоны делали именно то, что мне было нужно. Мне хотелось большего, поэтому я начал разбираться, как они сделаны.

Забавно, что в моём серьёзном увлечении программированием можно обвинить World of Warcraft. Оказалось, что код был написан на языке Lua. Аддоны — это просто парочка файлов исходного кода на .lua в папке, напрямую загружаемых в игру. Барьер входа был невероятно низок: достаточно отредактировать файл, сохранить его и перезапустить интерфейс. То, что игра загружала твой исходный код и ты мог видеть его работу, было настоящим волшебством!

Мне это невероятно нравилось, и вскоре я уже практически не играл в игру, а занимался только написанием аддонов. За следующие два года я опубликовал приличное их количество; в большинстве случаев я просто копировал чужой код и рефакторил/комбинировал/настраивал его под свои нужды.

Читать далее
Total votes 117: ↑116 and ↓1+115
Comments42

Кто на самом деле пользуется is-odd и is-even?

Level of difficultyEasy
Reading time4 min
Views15K

Разработчики любят подшучивать над раздуванием зависимостей Javascript (и вполне имеют на это право, учитывая историю пакетов наподобие left-pad); при этом часто упоминаются пакеты is-even и is-odd. Поэтому я заинтересовался, кто же на самом деле их использует?

Читать далее
Total votes 28: ↑27 and ↓1+26
Comments18

Как работают трансформеры: разбираем математику

Level of difficultyMedium
Reading time28 min
Views16K

В этом посте я представлю подробный пример математики, используемой внутри модели трансформера, чтобы вы получили хорошее представление о работе модели. Чтобы пост был понятным, я многое упрощу. Мы будем выполнять довольно много вычислений вручную, поэтому снизим размерность модели. Например, вместо эмбеддингов из 512 значений мы используем эмбеддинги из 4 значений. Это позволит упростить понимание вычислений. Мы используем произвольные векторы и матрицы, но при желании вы можете выбрать собственные значения.

Как вы увидите, математика модели не так уж сложна. Сложность возникает из-за количества этапов и количества параметров. Перед прочтением этой статьи я рекомендую прочитать пост Illustrated Transformer (или читать их параллельно) [перевод на Хабре]. Это отличный пост, объясняющий модель трансформера интуитивным (и наглядным!) образом, поэтому я не буду объяснять то, что уже объяснено в нём. Моя цель заключается в том, чтобы объяснить, как работает модель трансформера, а не что это такое. Если вы хотите углубиться в подробности, то изучите известную статью Attention is all you need [перевод на Хабре: первая и вторая части].

Читать далее
Total votes 40: ↑40 and ↓0+40
Comments8

Сжимаем текст в изображения PNG

Level of difficultyEasy
Reading time2 min
Views5.7K

(Наверно, это глупая идея. Но иногда даже самые глупые идеи приводят к неожиданным результатам.)

Текст шекспировской трагедии «Ромео и Джульетта» состоит примерно из 146 тысяч символов. Благодаря английскому алфавиту каждый символ можно описать одним байтом. Так что размер текстового файла в обычном Unicode составляет примерно 142 КБ.

В статье Adventures With Compression её автор JamesG размышляет о соревнованиях по сжатию текста и предлагает интересную мысль...

Читать далее
Total votes 19: ↑17 and ↓2+15
Comments38

Я разработчик, а не компилятор

Level of difficultyEasy
Reading time3 min
Views52K

Недавно у меня было телефонное собеседование, на котором мне задавали разнообразные вопросы по Java. Это стандартное собеседование, и большинство вопросов тоже было вполне стандартным:

Что такое полиморфизм?

В чём разница между List и Set? Когда стоит использовать первое, а когда второе?

Где можно столкнуться со взаимной блокировкой (deadlock)?

В чём разница между строгой и слабой типизацией?

В основном вопросы были вполне закономерными. Лично мне не нравится вопрос про полиморфизм, ведь он настолько тесно связан с большинством объектно-ориентированных языков и наследованием, что многие люди, используя его (например, при переопределении или перегрузке метода), даже не думают «О! Это же полиморфизм в действии!». Вместо этого я бы задал вопрос «Что такое наследование, и где оно используется», потому что в большинстве объектно-ориентированных языков для него есть ключевое слово или паттерн. Но это уже мои личные предпочтения, и я вполне понимаю логику проводившей собеседование компании.

Читать далее
Total votes 145: ↑136 and ↓9+127
Comments201

Быстрый парсинг 8-битных целых чисел

Level of difficultyEasy
Reading time6 min
Views11K

Допустим, вам нужно быстро распарсить 8-битные целые числа (0, 1, 2, …, 254, 255) из строки ASCII/UTF-8. Задача взята из проекта simdzone под руководством Йероена Коеккоека (NLnet Labs). Дана строка и её длина: например, ’22’ и длина 2. Наивное решение на C может выглядеть так:

Читать далее
Total votes 31: ↑31 and ↓0+31
Comments21

Information

Rating
Does not participate
Location
Россия
Registered
Activity