All streams
Search
Write a publication
Pull to refresh
1940
298.4

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

Send message

Что нужно знать о современном CSS (весна 2024 года)

Level of difficultyMedium
Reading time15 min
Views33K

Цель этого руководства — познакомить вас со списком новых (потрясающих) возможностей, недавно появившихся в CSS.

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

Читать далее

Сложно ли генерировать 1024-битные простые числа?

Level of difficultyEasy
Reading time28 min
Views13K

Простые числа удивительны!

С одной стороны, их легко объяснить: это просто числа, которые делятся только на единицу и на себя; с другой стороны, они содержат в себе бесконечную сложность. Они встречаются во множестве разных сфер, от математических концепций и гипотез до любопытных визуализаций и криптографии, лежат в основе многих Интернет-стандартов и протоколов безопасности, которые мы используем ежедневно.

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

Вызов

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

Генерировать простые числа, способные генерировать ключи для алгоритма RSA

На момент написания этой статьи хорошей длиной ключей RSA считаются 2048 битов. Ключи RSA генерируются перемножением двух простых чисел, так что для получения 2048-битного ключа нам нужны два числа длиной примерно 1024 бита. Это ограничивает рамки задачи генерацией 1024-битных простых чисел. Теперь вы знаете, откуда взялось число из заголовка поста.

Читать далее

Почему я отказался от разработки игр на Rust, часть 4

Level of difficultyMedium
Reading time12 min
Views5.4K

Часть 1
Часть 2
Часть 3

Dynamic borrow checking вызывает неожиданные вылеты после рефакторинга

В процессе написания статьи я обнаружил ещё один случай вылета нашей игры из-за пересекающегося World::query_mut. Я работаю с hecs уже около двух лет, такие проблемы — это не тривиальные «ой, я случайно сделал вложенными два запроса», с которыми сталкиваешься, только начав работать с библиотекой. Скорее, это ситуация, когда одна часть кода, находящаяся на верхнем уровне, запускает выполняющую что-то систему, а затем независимая часть кода делает что-то простое с ECS где-то глубоко внизу; после крупномасштабного рефакторинга они неожиданно оказываются пересекающимися.

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

Но эта проблема возникает не только в ECS. У нас она много раз возникала при использовании RefCell<T>, когда два .borrow_mut() создают пересечение и вызывают неожиданный вылет.

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

Читать далее

Демо City In A Bottle – система рейкастинга в 256 байтах

Level of difficultyMedium
Reading time8 min
Views3.9K

Привет всем любителям size coding, сегодня я расскажу о чём-то потрясающем: крошечном движке трассировки лучей (raycasting) и генераторе города, умещающихся в автономном файле HTML размером 256 байтов.

В этом посте я поделюсь секретами работы этой волшебной программы. Возможно, вы уже видели этот пост в моём Twitter. После публикации два года назад он стал самым популярным моим твитом.

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

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

Читать далее

Двоичный поиск против вероятностного

Level of difficultyEasy
Reading time7 min
Views6.9K

Внутри Dolt, первой в мире базе данных SQL с полнофункциональными возможностями контроля версий, таится много интересной computer science. Недавно я писал о системе хранения Dolt, в ней есть очень тонкая особенность — применение вероятностного поиска на больших выборках 64-битных целых чисел.

В любом учебном плане по Computer Science есть курс алгоритмов. Моим был CS 102, и одним из пунктов, который объяснялся в нём досконально, было то, что поиск — это, по сути, задача O(log2(N)) при условии, если данные отсортированы. За свою карьеру я многократно встречался с этим в том или ином виде — если сортируешь информацию и сохраняешь её, то стоит ожидать, что для поиска потребуется время O(log2(N)). В общем случае мы соглашаемся на время поиска O(log2(N)), потому что оказывается, что можно перебрать большой объём данных с логарифмическим коэффициентом масштабирования. Эта система работает, потому что мы уже почти автоматически сортируем всё заранее.

Но что если мы добавим дополнительные ограничения на наши данные, которые позволят нам выполнять поиск за константное время?

Будет ли эта статья историей о необязательной оптимизации? Да, будет. В этом конкретном случае поиск будет занимать гораздо меньше времени, чем чтение с диска. Мы говорим о величинах менее чем 0,1% от суммарного времени. Будет ли эта статья историей о преждевременной оптимизации? Нет, не будет. Это бы подразумевало, что мы не осознаём, что время тратится не на то. Эта статья — история о заманчивости алгоритма константного времени.

Читать далее

Почему я отказался от разработки игр на Rust, часть 3

Level of difficultyMedium
Reading time16 min
Views12K

Часть 1
Часть 2

Ситуация с GUI в Rust просто ужасна

В сообществе Rust ходит шутка, что на 5 игр существует 50 игровых движков; наверно, ещё одна такая шутка нужна про фреймворки GUI. Люди пробуют разные подходы, что, учитывая полную обобщённость Rust как языка, имеет смысл. Но в этой статье мы говорим о разработке игр, и я считаю, что в этой сфере у нас не просто дефицит, а полное отсутствие решений.

Под UI я здесь подразумеваю не UI для создания редактора, а внутриигровой UI. То, что должно быть очень стилизовано и наглядно. По моему опыту, самое сложное при создании игрового UI — это не реализация привязки данных, не реактивное обновление элементов и даже не выбор наилучшего способа описания структуры. Самое сложное — это настройка внешнего вида и стиля UI.

Я даже не касаюсь тем наподобие частиц в UI и различных эффектов, которые могут понадобиться пользователю. Очевидно, что полностью независимая от всего библиотека GUI не может иметь сложных шейдерных эффектов и частиц, но мне кажется, что это тоже стало частью общей проблемы. Библиотеки GUI перекладывают всю эту ношу на пользователя, поэтому каждому пользователю приходится заново изобретать велосипед в выбранном фреймворке/движке.

Читать далее

Ищем баги в коде браузера при помощи фаззинга

Reading time7 min
Views3K

Наш браузер Ladybird неплохо справляется с качественно отформатированным веб-контентом, но я решил, что будет полезно проверить его инструментами для исследования безопасности. Поэтому сегодня мы воспользуемся Domato 🍅 — DOM-фаззером из Google Project Zero, чтобы провести стресс-тест Ladybird и устранить найденные в процессе ошибки.

Работает это следующим образом: Domato генерирует рандомизированные веб-страницы со множеством по большей части валидного, но странного HTML, CSS и JavaScript. Я загружу эти страницы в отладочную сборку Ladybird и посмотрю, что получится.

Читать далее

Почему я отказался от разработки игр на Rust, часть 2

Level of difficultyMedium
Reading time16 min
Views11K

Часть 1

Обобщённые системы не приводят к интересному геймплею

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

Это сильный аргумент, на который почти нечем ответить, за исключением того, что обобщённые системы приводят к скучному геймплею. Я был довольно активен в сообществе разработчиков игр на Rust, поэтому видел множество проектов, которые создают другие; разумеется, предлагаемые ими рекомендации коррелируют с теми играми, которые они создают. Люди, которые склонны создавать красиво спроектированные системы, работающие полностью обобщённо, обычно создают не совсем игры, а симуляции того, что со временем станет игрой; в таких симуляциях геймплеем часто считается даже нечто типа «у меня есть персонаж, который может двигаться».

Читать далее

Почему я отказался от разработки игр на Rust, часть 1

Level of difficultyMedium
Reading time19 min
Views34K

Предисловие: этот пост представляет собой очень длинный перечень мыслей и проблем, возникавших у меня за годы работы; также в нём рассматриваются некоторые из аргументов, которые мне часто говорили. В посте выражено моё мнение, сформировавшееся у меня в процессе разработки игр на Rust в течение многих тысяч часов на протяжении многих лет и после множества завершённых игр. Это не хвастовство и не показатель успеха, я просто хочу сказать, что вложил достаточно много усилий в Rust; здесь не получится сказать «когда наберёшься опыта, тебе всё станет понятно».

Пост не будет ни научной оценкой, ни A/B-исследованием. Это моё личное мнение после разработки игр на Rust маленькой инди-командой (два человека) в попытках заработать достаточно денег, чтобы финансировать процесс. Мы не одни из тех разработчиков с бесконечными финансами от инвестора и многолетним запасом времени. Если вы находитесь в этой категории и получаете удовольствие от многолетней разработки систем, то всё написанное ниже к вам не относится. Я рассматриваю всё с такой точки зрения: «Мне хочется создать игру максимум за 3-12 месяцев, чтобы люди могли сыграть в неё, а я — немного заработать». Статья не написана с точки зрения «Я хочу изучить Rust, а разработка игр — это весело», хотя это и вполне нормальная цель; просто она никак не согласуется с тем, чего хотим мы — заниматься разработкой игр коммерчески успешным и самодостаточным образом.

Мы выпустили несколько игр на Rust, Godot, Unity и Unreal Engine, и многие люди сыграли в них в Steam. Мы создали с нуля собственный игровой 2D-движок с простым рендерером, а также в течение нескольких лет использовали Bevy и Macroquad во многих проектах, некоторые из которых были очень нетривиальными. Кроме того, я бэкенд-разработчик на полную ставку и пишу код на Rust. Этот пост — не какое-то поверхностное мнение после изучения нескольких туториалов или разработки небольшой игры для геймджема. За три с лишним года мы написали сильно больше ста тысяч строк кода на Rust.

Задача этого поста — развеять популярные и часто повторяемые аргументы. Но это всё-таки субъективное мнение; по большей части я написал пост, чтобы не объяснять снова и снова одно и то же. Пусть это будет справочный материал о том, почему мы, скорее всего, откажемся от Rust как от инструмента для разработки игр. Мы ни в коем случае не планируем прекращать создавать игры, просто не будем делать это на Rust.

Читать далее

Как Figma удалось открыть себе путь к почти бесконечному масштабированию баз данных

Level of difficultyMedium
Reading time17 min
Views12K

О нашем девятимесячном пути к горизонтальному шардингу Postgres-стека Figma и о возможности обеспечения (почти) бесконечной масштабируемости.

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

С 2020 года стек баз данных Figma вырос почти в сотню раз. Это хорошая проблема, ведь она означает, что наш бизнес расширяется. Но в то же время она стала причиной технических сложностей. В течение последних четырёх лет мы усиленно старались не отставать от прогресса и избегать потенциальных проблем, связанных с ростом. В 2020 году у нас работала единственная база данных Postgres, которая хостилась на самом большом физическом инстансе AWS, но к концу 2022 года мы уже создали распределённую архитектуру с кэшированием, репликами для чтения и десятком вертикально разделённых баз данных. Мы разбили группы связанных таблиц (например, «Figma files» или «Organizations») на отдельные вертикальные разделы, что позволило нам обеспечить удобство инкрементального масштабирования и оставить достаточно пространства для дальнейшего роста.

Читать далее

Как я снизил время инкрементальных сборок Rust на 40%

Level of difficultyMedium
Reading time9 min
Views4K

Я форкнул и модифицировал компилятор Rust rustc. Одна фича — кэширование раскрытия процедурных макросов — привела к снижению времени инкрементальных сборок на 11-40% в различных реальных крейтах. Благодаря этому ускорились dev-сборки и меньше стал тормозить rust-analyzer (IDE IntelliSense).

Если вы специалист в повышении производительности компилятора Rust, то можете сразу перейти к разделу «Кэширование раскрытия макросов: ускорение инкрементальных сборок Rust на 40%».

Читать далее

Рулетка онбординга: ежедневно удаляем аккаунты сотрудников

Level of difficultyEasy
Reading time6 min
Views9K

Я большой поклонник автоматизированных тестов и достаточно дисциплинированный их автор. Проектирование ПО крайне сложно реализовать функционально корректно и ещё сложнее избежать регрессии в дальнейшем. Как сказал Майкл Фезерс, «легаси-код — это весь код, у которого нет тестов».

Некоторые вещи, например, конечные точки серверов, схемы баз данных и компоненты библиотек UI тестировать очень просто.

Другие вещи тестировать сложнее, например, конечные точки, вызывающие сторонние API, веб-страницы на React со сложными состояниями и асинхронные задачи, требующие детализированных записей баз данных. Airbnb мне было сложно тестировать письма со сбросом паролей, потому что отправка электронной почты выполнялась через аутсорсный сервис.

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

Читать далее

Клонируем ноутбук при помощи NVME over TCP

Level of difficultyEasy
Reading time3 min
Views14K

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

Читать далее

Как в git работает HEAD

Level of difficultyEasy
Reading time5 min
Views22K

Недавно я провела в Mastodon опрос о том, насколько мои читатели уверены в том, что они хорошо понимают работу HEAD в Git. Результаты (на основании примерно 1700 голосов) меня немного удивили:

10% — 100%

36% — достаточно сильно уверен

39% — уверен в некоторой степени

15% — представления не имею

Меня удивило, что люди не уверены в своём понимании: я-то считала, что HEAD — это довольно простая тема.

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

Читать далее

Дилемма ИИ: когда обучение больших языковых моделей заходит в тупик

Level of difficultyEasy
Reading time11 min
Views5.7K

ИИ готовится заменить сотни тысяч должностей не только в разработке ПО, но и во множестве других областей: в журналистике, творческой работе, общении с покупателями и так далее. Это та же самая мантра, которую мы слышим по поводу каждой технологической инновации: «Компьютер полностью заменит людей». Старая история из фильмов про терминаторов.

Хотя я уже перечислил некоторые возможные последствия для ПО в своей статье «Мы снова в кризисе ПО, но в ближайшее время ИИ никого не заменит», мне бы хотелось рассмотреть, что произойдёт, если большие языковые модели (Large Language Model, LLM) полностью заменят человеческий труд. Содержание дилеммы будет практически одинаковым для всех областей, но я сосредоточусь на разработке ПО, потому что самые громкие заявления об LLM звучат как раз в её сторону.

Читать далее

Современные команды и фичи Git, которыми стоит пользоваться

Level of difficultyEasy
Reading time5 min
Views44K

Мы, разработчики ПО, пользуемся git каждый день, однако большинство из нас применяет только самые основные команды, например, addcommitpush и pull, как будто на дворе по-прежнему 2005 год.

С тех пор в Git появилось множество фич, пользование которыми может сильно упросить вашу жизнь. Так давайте исследуем некоторые из недавно добавленных современных команд git, о которых вам стоит знать.

Читать далее

Как калькуляторы вычисляют синус?

Level of difficultyEasy
Reading time3 min
Views58K

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

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

Читать далее

Почему Facebook* не использует Git

Reading time8 min
Views42K

Я работаю над созданием Graphite, источником вдохновения для которого стал внутренний инструментарий Facebook. Когда я решил создать стартап с друзьями, то никогда раньше не слышал о Mercurial, хотя всегда страстно любил инструменты разработчика. Мой предыдущий опыт разработки включал в себя личные проекты, домашнюю работу в колледже, разработку для iOS в Google и развитие инфраструктуры в Airbnb. На протяжении всей моей карьеры использование git было таким же естественным, как воздух. Он настолько популярен, что лично я считал его единственным подходящим инструментом для создания изменений в коде и управления ими.

Забавно, что специалист по Mercurial Грегори Gregory Szorc работал рядом со мной в Airbnb, хотя я знал его только как приятного коллегу, но не представлял, что он контрибьютор.

В 2021 году мои коллеги по команде Томас и Ник раскрыли мне глаза. Они пришли из Facebook и, к моему удивлению, едва знали Git. Зато они имели глубокое понимание паттернов Mercurial и рабочего процесса Facebook на основе «многослойных diff» (stacked diff). Со временем они убедили меня в полезности этого паттерна и мы развернули направление развития компании, чтобы реализовать многослойные diff для разработчиков GitHub.

Но пост посвящён не нашему стартапу. Он о важном вопросе, не дававшем мне покоя последние три года. Почему фейсбукеры не пользуются Git? Зачем они выбрали Mercurial и создали на его основе собственные рабочие процессы? Я знаю что Google не пользуется Git, но это логично, культура разработки Google возникла на пять лет раньше Git. Facebook же был основан примерно в то же время, что и создан Git, около 2004 года, и ко времени, когда Facebook начал серьёзно выбирать инструментарий для управления исходниками, Git был старше и популярнее Mercurial. Так почему же Facebook не использует Git?

Читать далее

CSS для печати на бумаге

Reading time10 min
Views15K

По работе я довольно часто занимаюсь созданием генераторов печати на HTML для воссоздания и замены форм, которые компания традиционно заполняла от руки на бумаге или в Excel. Это позволяет компании переходить на новые веб-инструменты, в которых форма автоматически заполняется по параметрам URL из нашей базы данных, создавая при этом тот же результат на бумаге, к которому все привыкли.

В этой статье я объясню основы CSS, управляющие внешним видом веб-страниц при печати, и дам пару советов, которые могут вам помочь в этом.

Читать далее

Это слишком опасно для C++

Reading time6 min
Views35K

Некоторые паттерны стало возможно использовать на практике только благодаря безопасности Rust по памяти, а на C++ они слишком опасны. В статье приведён один такой пример.

Работая над внутренней библиотекой, написанной на Rust, я создал тип ошибок для парсера, у которых должна быть возможность сделать Clone без дублирования внутренних данных. В Rust для этого требуется указатель с подсчётом ссылок (reference-counted pointer) наподобие Rc.

Поэтому я написал свой тип ошибок, использовал его как вариант ошибок fallible-функций, и продолжил двигаться дальше.

Читать далее

Information

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