Pull to refresh
523
325.7

Пользователь

Send message

Советы по программированию, которые бы я дал себе 15 лет назад

Level of difficultyMedium
Reading time8 min
Views23K


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

▍ Если ты (или твоя команда) постоянно стреляешь себе в ногу, то почини ружьё


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

Когда я занимался разработкой для iOS, то использовал CoreData и подписывался на изменения нескольких view. Обратный вызов подписки поступал в тот же поток, из которого было запущено изменение. Иногда это был основной поток, а иногда — фоновый. В разработке для iOS важно то, что вносить изменения в UI можно только в основном потоке, иначе приложение вылетит. Поэтому подписка могла работать нормально, но потом ломалась, когда кто-то запускал изменение из фонового потока или вы позже добавляли обновление UI.

Все без раздумий воспринимали это как что-то само собой разумеющееся, и об этом часто говорили в ревью для новичков в команде. Время от времени кто-нибудь ошибался, и мы добавляли DispatchQueue.main.async, когда видели отчёт о сбое.

Я решил это исправить. У меня ушло десять минут на внесение изменений в слое подписки, теперь подписчики вызывались в основном потоке, что позволило избавиться от целого класса сбоев и сняло с нас часть умственной нагрузки.
Читать дальше →
Total votes 41: ↑39 and ↓2+54
Comments13

GPU для дата-центров

Level of difficultyEasy
Reading time6 min
Views3.4K

Серверный узел с восемью GPU-ускорителями AMD Instinct MI325X (2,3 ТБ видеопамяти, 8×750 Вт)

Современные дата-центры уже не такие, как прежде. Раньше на типичный сервер поставили бы 144-ядерный CPU, много RAM и десяток HDD/SSD. Но теперь приоритеты меняются, в первую очередь из-за высокого спроса на машинное обучение (ML) и приложения LLM. Хотя аппетит к памяти только вырос, но процессоры нужны другие.

И крупным корпорациям, и маленьким компаниям нужно железо для обсчёта ИИ-приложений. Это GPU-ускорители, NPU (Neural Processing Unit) и TPU (Tensor Processing Unit), AI-чипы нового поколения. Нужны серверы с GPU. Открываются даже специализированные GPU-облака на растущем спросе.
Читать дальше →
Total votes 23: ↑22 and ↓1+33
Comments1

Празднуем день рождения на древнем компьютере с BASIC

Level of difficultyEasy
Reading time10 min
Views4K

Этим летом я занимался созданием нового приложения для машины, продажи которой закончились в 1980 году, и которая не была рассчитана на поддержку графики, сети и даже букв в нижнем регистре. Её продавала компания, обанкротившаяся десяток лет назад. Приложение было специально разработано под единственного пользователя — моего отца, которому в позапрошлую пятницу исполнилось семьдесят лет. Представляю вашему вниманию MTS-70:
Фото


Программа MTS-70 была разработана для Radio Shack TRS-80 Model 1 (примерно 1979 год). У неё есть шесть уникальных и очень забавных функций, неинтересных никому, кроме меня и (в идеале) моего отца (инициалы которого, разумеется, MTS):

  1. Чат с Dadbot — инстансом gpt-3.5 с fine-tuning на основе текстовых переписок между мной и отцом на протяжении пятнадцати лет.
  2. Воспроизведение «Happy birthday» (через 500-бодный кассетный вывод данных; этот хак был необходим из-за отсутствия нативной поддержки звука в TRS-80).
  3. Морской прогноз на сегодня, в том числе прогнозы прилива и течений.
  4. Поиск ближайших концертов и мероприятий в Ист-Энде Лонг-Айленда (где живёт мой старик).
  5. Текстовая адвенчурная игра на основе LLM о выживании летом в Ист-Энде, дополненная забавными семейными байками.
  6. Игра в го (на доске 9×9 против достаточно сильного локального игрового движка).
Читать дальше →
Total votes 30: ↑30 and ↓0+51
Comments1

Два потока, одно ядро: как устроена одновременная многопоточность

Level of difficultyMedium
Reading time13 min
Views22K

Одновременная многопоточность (Simultaneous multithreading, SMT) — это функция, позволяющая процессору одновременно обрабатывать команды из двух разных потоков. Но задавались ли вы когда-нибудь вопросом, как это работает? Как процессор отслеживает два потока и распределяет ресурсы между ними?

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

Примечание: основная часть изложенного в статье относится к реализации SMT компании Intel, также называемой гипертредингом (hyper-threading). Она основана на научной статье компании, опубликованной в 2002 году.
Читать дальше →
Total votes 48: ↑46 and ↓2+68
Comments47

Вам следует написать новый (ужасный) язык программирования

Level of difficultyEasy
Reading time5 min
Views14K

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

Но из-за этого мы теряем возможность научиться чему-то новому. Я нашла это новое, когда создала язык, руководствуясь глупым принципом: поток управления должен осуществляться через исключения и ничего больше. Я создала его как шутку, но неожиданно для себя в процессе разработки получила новые знания.
Читать дальше →
Total votes 45: ↑43 and ↓2+55
Comments61

Любой может получить доступ к удалённым и приватным данным репозиториев GitHub

Level of difficultyMedium
Reading time6 min
Views47K

Кто угодно может получать доступ к данным из удалённых форков, удалённых репозиториев и даже приватных репозиториев GitHub. И эти данные доступны всегда. Это известно разработчикам GitHub, и они намеренно спроектировали систему таким образом.

Это настолько огромный вектор атак для всех организаций, использующих GitHub, что мы решили ввести новый термин: Cross Fork Object Reference (CFOR). Уязвимость CFOR возникает, когда форк одного репозитория может получить доступ к требующим защиты данным из другого форка (в том числе и к данным из приватных и удалённых форков). Аналогично Insecure Direct Object Reference, при CFOR пользователи передают хэши коммитов, чтобы напрямую получать доступ к данным коммитов, которые иначе были бы для них невидимыми.

Давайте рассмотрим несколько примеров.
Читать дальше →
Total votes 112: ↑104 and ↓8+125
Comments41

Как я портировал свой игровой движок с JavaScript на C

Level of difficultyMedium
Reading time13 min
Views9.1K

high_impact


tl;dr: high_impact — это маленький игровой движок для 2D-игр жанра «экшн». Он написан на C, компилируется для Windows, Mac и Linux, а также для WASM в вебе. Он был написан «по мотивам» моего игрового движка Impact на JavaScript, разработанный в 2010 году. Название high_impact — отсылка к тем временам, когда C считался языком высокого уровня.

Движок имеет лицензию MIT, исходники выложены на Github: github.com/phoboslab/high_impact

Видео из моего твита за 5 июля, демонстрирующее геймплей Biolab Disaster
Читать дальше →
Total votes 39: ↑38 and ↓1+53
Comments0

RSS-агрегатор и RSS-мост на виртуальном сервере

Level of difficultyMedium
Reading time6 min
Views3.1K


Формат RSS (Really Simple Syndication) хотя и довольно старая технология, но до сих пор очень популярная. Можно сказать, что сейчас она словно переживает второе рождение, особенно в условиях затруднённого доступа ко многим сайтам.

Это действительно самый удобный способ читать весь контент в одном месте, без рекламы и лишних отвлечений. Конечно, есть внешние RSS-агрегаторы и ридеры, но можно выбрать и другой вариант: запустить агрегатор на своём сервере и не зависеть от внешних факторов. Это даёт бóльшую свободу, потому что его функциональность в некоторых случаях даже шире, чем у специализированных сервисов.
Читать дальше →
Total votes 33: ↑33 and ↓0+53
Comments4

Factorio: оптимизации 2.0

Level of difficultyMedium
Reading time10 min
Views27K
Все мы любим строить всё больше и больше, поэтому когда сталкиваешься с ограничением UPS, это сильно расстраивает. Именно поэтому мы обязаны продолжать свой бесконечный процесс оптимизации игры.

▍ Оптимизация роботов (автор: Rseding)


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

Типичная фабрика с кучей дронстанций (Roboport)

Дронстанции никогда не были «медленными», но они всегда присутствуют на карте, и у игроков есть мотивация строить их в больших количествах; к тому же, их будет ещё больше в грядущем Space Age, где нужно будет многое делать удалённо. Сохранение, полученное после последней сессии плейтестинга, снова показало, что они отнимают небольшое, но ненулевое количество времени, поэтому я снова задумался о них.
Читать дальше →
Total votes 55: ↑53 and ↓2+63
Comments28

Находим случайный seed, решающий задачу с LeetCode

Level of difficultyMedium
Reading time6 min
Views7.6K

У меня есть хобби — решать задачи LeetCode непредназначенным для этого образом, часто при помощи запутанных однострочников. Такие самостоятельно накладываемые ограничения делают задачки интереснее и заставляют искать нестандартные решения.

Одним из ежедневных челленджей LeetCode была такая задача (я немного упростил её для понятности):

Есть список из $k$ уникальных строк битов, каждая из которых имеет длину $k$. Сгенерировать новую строку длиной $k$, отсутствующую в этом списке.

Например, если у нас есть список "010", "110", "111", то возможным решением будет "001". Задача с LeetCode имеет большой набор тестов — 183 тестовых сценариев с $1≤k≤16$, а точную формулировку задачи можно найти здесь.

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

class Solution:
    def findDifferentBinaryString(self, nums: List[str]) -> str:
        random.seed((69299878 + sum(ord(c)*(i*j+111) for (i, n) in enumerate(nums) for (j, c) in enumerate(n))) % 999999999)
        return ''.join(random.choice('01') for _ in nums)

Можете попробовать это решение самостоятельно (оно должно работать, если LeetCode не обновил свой набор тестов. Если это произошло, сообщите мне об этом).

Ниже я расскажу, как это сделал.
Читать дальше →
Total votes 36: ↑35 and ↓1+51
Comments7

Пишем за неделю 3D-редактор на C

Level of difficultyMedium
Reading time6 min
Views9.2K
Прошлой осенью я участвовал в недельном мероприятии по программированию Wheel Reinvention Jam. Смысл этого джема заключается в том, чтобы взглянуть по-новому на уже существующие программные системы. Я написал для него 3D-редактор под названием ShapeUp. Пост будет понятнее, если вы сначала посмотрите видео-демо ShapeUp. Можно попробовать ShapeUp в браузере.

Вот, как он выглядит:

Майк Вазовски!

3D-редактор


Я ненавижу тормознутость компилятора Typescript (поверьте, это относится к теме статьи). Джем показался мне подходящей возможностью реализовать более быстрое подмножество Typescript, обгоняющее по скорости tsc. Мне показалось, что проект можно реализовать, если начать с парсера Typescript esbuild or Bun. Но потом ко мне пришло понимание, что успешный результат будет выглядеть как команда терминала, выполняющая работу быстрее другой. Не особо впечатляюще в качестве демо. Мне хотелось создать крутое демо, поэтому я выбрал 3D.
Читать дальше →
Total votes 51: ↑46 and ↓5+61
Comments7

Как сломать сисадмина

Level of difficultyEasy
Reading time6 min
Views34K
На планете Шелезяка всё было просто: злодей подсыпал алмазную пыль в маслёнки, и вот уже роботы выведены из строя и подают сигналы бедствия. На планете Земля, в душных и кондиционированных офисах, на производствах и в больницах, на удалёнке и в серверной злые и порой недалёкие пользователи делают больно иначе: доводят системных администраторов до белого каления своими действиями и без алмазной пыли. А потом, когда уже всё работает, не то что шоколадку выпить — спасибо не услышишь! День системного администратора — самое время войти в чертоги коварства, разобраться в приёмах злодеев и спокойно пойти отмечать день, разрывая на груди футболку за свитч и разделение прав доступа.


Итак, 12 верных способов сломать сисадмина.
Читать дальше →
Total votes 56: ↑52 and ↓4+62
Comments35

Красота и изящество таблицы ASCII

Level of difficultyMedium
Reading time7 min
Views10K
Если вы программист или хотя бы немного связаны с программированием1, то без сомнения сталкивались с таблицей ASCII.

Таблица ASCII полезна. Но знали ли вы, что она ещё красива и изящна?

Сегодня даже не близкие к программированию люди могут знать об ASCII благодаря книгам и фильмам наподобие «Марсианина»2

ASCII по-прежнему с нами; даже если вы передаёте современный Unicode3, то должны знать, что самый популярный формат кодировки UTF-8 специально спроектирован как обратно совместимый с ASCII! Декодировав эту статью как ASCII, вы в целом поймёте её смысл… если закроете глаза на мусорные символы в конце предложений (прим. ред.: имеет смысл только для оригинальной статьи на английском).
Читать дальше →
Total votes 54: ↑53 and ↓1+73
Comments56

Установка LLM на скромном VPS

Level of difficultyMedium
Reading time6 min
Views8.1K

«Я тебя завалю, если ещё раз упомянешь AI», — писал автор нашумевшей статьи. В самом деле, хайп вокруг ИИ всем надоел. Но мы всё-таки рискнём поговорить о том, какую LLM поставить на своём сервере и зачем.

Сразу упомянем, что на серверах RUVDS установлены видеокарты NVIDIA Quadro P4000 (на фото). Карты довольно слабенькие, так что подойдут скорее для проектов в образовательных целях и т. д. Тем более что под VPS выделяется максимум 1 ГБ видеопамяти. Но даже в таких спартанских условиях можно запустить LLM.

Кстати, о VPS с видеокартой. Несколько лет назад мы уже писали о сферах их применения и даже проводили тесты. Всё это можно найти здесь.
Читать дальше →
Total votes 32: ↑30 and ↓2+46
Comments17

Профессиональные игроки в покер знают оптимальную стратегию, но не всегда её используют

Level of difficultyEasy
Reading time8 min
Views15K
Сегодня игроки в покер могут использовать ИИ для поиска оптимальной стратегии игры, но делают это не так часто.


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

Вопрос о том, использовать ли оптимальную с точки зрения теории игр стратегию или пользоваться хитростями — это главная тема обсуждений в покере высокого уровня. Его математические основы заложены ещё восемьдесят лет назад, но быстрый прогресс в развитии ИИ выдвинул математику середины двадцатого века на передний план современных игр. Новые инструменты учат игроков в покер оптимальной стратегии, но почему же те постоянно от неё отказываются?
Читать дальше →
Total votes 31: ↑30 and ↓1+41
Comments10

CSS-классы вредны

Level of difficultyMedium
Reading time13 min
Views21K

Если вы когда-нибудь заглядывали за кулисы пользовательских веб-интерфейсов, то знаете для чего нужно свойство class. Оно ведь нужно для связи HTML с CSS, правда? Сейчас я расскажу о том, почему настало время отказаться от него. Имена классов — это архаичная система, используемая как неудачный посредник для примитивов UI; ещё хуже то, что они создают ужасные сочетания, приводящие к комбинаторному взрыву странных пограничных случаев. Давайте изучим этот вопрос, начав со скучного урока истории, который вы уже слышали миллион раз.
Читать дальше →
Total votes 75: ↑66 and ↓9+79
Comments113

Побеждаем компилятор в скорости при помощи ассемблера

Level of difficultyMedium
Reading time13 min
Views8.2K

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

Тем не менее, иногда до нас доносятся слухи.

Написанные в древних томах, подслушанные в тайных покоях, начертанные на стенах разрушенных храмов, упоминаемые в загадочных текстах, они рисуют чёткую картину:

Компиляторы плохо справляются с генерацией кода для интерпретаторов, и можно превзойти их, написав интерпретатор на языке ассемблера.
Читать дальше →
Total votes 42: ↑40 and ↓2+56
Comments46

Как правильно тестировать конкурентные структуры данных

Level of difficultyMedium
Reading time19 min
Views5.5K

Есть потрясающая библиотека Rust под названием loom, которую можно использовать для тщательного тестирования неблокируемых (lock-free) структур данных. Я давно хотел разобраться, как она работает. И сейчас хочу! Но недавно я случайно реализовал небольшой эксперимент, который, как мне кажется, содержит часть идей loom, поэтому о нём стоит написать. Моя цель — не научить вас тому, что нужно использовать на практике (если вы хотите этого, то почитайте документацию loom), а, скорее, вывести пару идей из фундаментальных принципов.
Читать дальше →
Total votes 33: ↑33 and ↓0+46
Comments3

Профайлер памяти. Зачем он нужен и как использовать

Level of difficultyMedium
Reading time6 min
Views5.4K


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

Профайлер можно использовать не только в разработке, но и в системном администрировании, чтобы отслеживать рабочие процессы конкретных приложений, скриптов и задач.
Читать дальше →
Total votes 24: ↑22 and ↓2+31
Comments2

Как я запустил Linux с Google Drive

Level of difficultyMedium
Reading time10 min
Views20K

Я грешен: во мне есть дух соперничества. Когда я услышал, что мой друг заставил Linux загружаться с NFS, мне обязательно нужно было его превзойти. Я обязан был доказать, что могу сделать что-то сложнее, лучше, быстрее, сильнее [прим. пер.: в оригинале отсылка к композиции Daft Punk «Harder, Better, Faster, Stronger»].

Как и все хорошие проекты, этот начался с идеи.

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

На грани безумия мой утомлённый мозг придумал мой magnum opus: запуск Linux с рута Google Drive.

▍ Но как?


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

Мне достаточно было установить программы FUSE в initramfs ядра Linux и сконфигурировать сеть. В этом ведь не должно быть ничего сложного, так?
Читать дальше →
Total votes 51: ↑50 and ↓1+69
Comments6
1
23 ...

Information

Rating
Does not participate
Works in
Registered
Activity