Обновить
553
325.7
Sergei Kushnirenko@dalerank

Люблю (ш)кодить, алгоритмы и старые авто.

Отправить сообщение

Почему у нас нет кешей L5?

Уровень сложностиПростой
Время на прочтение13 мин
Охват и читатели21K

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

Первое, что нужно понять: процессор не является абстрактным вычислителем, а вполне себе реальный кусок кремния размером примерно с ноготь большого пальца, на котором размещены миллиарды транзисторов и когда мы говорим «данные передаются из памяти в регистр», то мы буквально имеем в виду, что электрический сигнал проходит по металлическому проводнику длиной в несколько миллиметров или сантиметров. И это тоже расстояние, пусть и ничтожное по человеческим меркам, но при тактовой частоте 3–4 ГГц оно уже имеет значение, просто потому что за один такт сигнал в идеальных условиях будет проходить всего 10 сантиметров, а в металлическом проводнике на кристалле и того меньше.

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

Читать далее

Нескучное программирование. Обобщения (ч.1)

Время на прочтение22 мин
Охват и читатели8.9K

Представьте на минуту, что C++ — это не набор странных ключевых слов и ошибок линковки, а всего лишь ещё один способ поговорить о мире вокруг нас: о людях, числах, цветах, событиях и котах. Мы привыкли думать о программировании как о чём‑то сугубо техническом, где важно запомнить синтаксис, расставить точки с запятой и “угадать”, чего сейчас хочет компилятор. 

Но если задать себе вопрос «а чем вообще оперирует программа?», внезапно выясняется, что за всеми этими int, struct и template прячутся довольно простые и понятные идеи: вещи, их свойства, группы похожих вещей и правила, по которым одни вещи превращаются в другие.

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

Когда философы и логики говорят об абстрактных сущностях, они имеют в виду индивидуальные вещи, которые не существуют в пространстве и времени так, как существуют стол, человек или компьютер, а как нечто неизменное: например, число 13 или сам по себе синий цвет не родились в какой‑то момент и не "умирают" через какое‑то время, это не объекты физического мира, а идеи, с которыми мы работаем в голове и в математике. 

Читать далее

О радости программирования и невесомости достижений

Время на прочтение8 мин
Охват и читатели20K

Я отношусь к тому постепенно вымирающему поколению разработчиков, которым выпала странная привилегия писать программный код в его самой чистой, первозданной форме, создавать каждую строчку вручную, собственными руками и головой, без всяких умных копайлотов-помощников, без промптов, без автодополнения, которое якобы знает что ты хочешь написать лучше тебя самого. Голая логика алгоритмов, литры выпитого кофе и мигающий курсор в пустом файле открытой IDE, когда мозг пытается удержать в своей “оперативной” памяти всю архитектуру системы целиком. 

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

Я делал это не потому, что меня кто-то заставлял или потому что так требовало начальство, а просто потому что сам процесс создания работающей системы из ничего, исправление хитрых багов, построение сложных систем из простых компонентов – всё это было по-настоящему весело, приносило какое-то детское удовольствие от созидания. Когда наконец откидываешься в кресле от монитора после многих часов работы, смотришь на то что построил своими руками, и видишь что всё работает как задумано, и думаешь: "Да, я, блин, чертов гений, это всё сделал только я, и никто мне не помогал". Ну разве что SO и немного гуглежки.

Читать

Писать код проще, чем книгу о том, как писать код

Уровень сложностиПростой
Время на прочтение4 мин
Охват и читатели18K

Иногда книга начинается с одной статьи, опубликованной в нужный момент и в нужном Хабре и в моём случае всё действительно началось с публикации про аллокаторы, которая несмотря на обилие технического материала, кода и схем набрала больше всего плюсов среди моих статей на околоплюсовую и игродев разработку. А дальше и сам цикл Game++ постепенно вырос из отдельных технических размышлений о C++, архитектуре движков и производительности в связный нарратив. За спиной Game++ стоит еще больше узкотехнических материалов в блоге и вики моей компании и я бы рад ими поделиться, да и делюсь периодически, но сами понимаете выкладывать можно не всё и даже из то, что выложено на Хабре, частенько было подрезано, ибо NDA и секретные технологии-бла-бла-бла. Та статья стала точкой, когда я увидел, что разрозненные тексты на самом деле образуют скелет будущей книги, нужно лишь перестать относиться к ним как к «постам» и начать воспринимать как главы. Идея написать книгу не пришла просто так, и несколько не связанных между собой людей и компаний связались и предложили переписать цикл статей в виде книги.

Читать далее

Охота за красным fps

Уровень сложностиПростой
Время на прочтение25 мин
Охват и читатели13K

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

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

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

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

Оптимизируй это...

Почему универ не готовит программистов

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели17K

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

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

С одной стороны у нас движковый, анимационный и gameplay программист это буквально одна из самых дефицитных профессий в индустрии прямо сейчас, чтобы вы понимали в среднем нехватка по студиям больше 20% мидловых и помидорских позиций, т.е. не хватает как минимум одного спеца в каждой команде, куда ни ткни. А ребята из Epic Games, Unity, CD проджектов и прочих крупных студий постоянно жалуются, что не могут найти нормальных специалистов, которые реально умеют работать с современными движками, и они готовы платить безумные деньги (безумные по меркам штатов конечно, в старом свете все более приземленное, но тенденция та же) тем кто шарит в графике или может написать мультипоточный код, который не развалится на проде, или знает, как выжать лишние пару кадров из железа, но людей всё равно не хватает и это при том, что желающих работать в геймдеве очень и очень много.

Читать далее

Нескучное программирование. Важны ли компилятору имена

Время на прочтение8 мин
Охват и читатели15K

Есть старая шутка о том “чем отличается обычный программист на С++ от хорошего программиста на С++”? Первый пишет код, а второй может объяснить, почему он работает. 

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

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

Первый: «Что вообще может означать это имя здесь?»
Второй: «Если вариантов несколько, какой из них правильный?»

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

Читать далее

Нескучное программирование. И снова ограничения

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели13K

Хотя концепты действительно являются мощным и выразительным инструментом, у них есть принципиальные ограничения, о которых важно знать, чтобы не пытаться использовать их не по назначению. Эти ограничения не случайны и не являются «недоделками» языка, а отражают осознанное архитектурное решение, принятое комитетом C++.

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

template<typename T>
concept Recurse = Recurse<T>;

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

Читать далее

Нескучное программирование. Иерархия концептов

Уровень сложностиСложный
Время на прочтение13 мин
Охват и читатели15K

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

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

Немножко сложности...

Нескучное программирование.История концептов

Время на прочтение9 мин
Охват и читатели15K

История концептов в C++ – один из самых показательных примеров того, как язык развивается не линейно, а через десятилетия экспериментов, откатов и переосмыслений. Первые идеи, которые мы сегодня называем концептами, появились ещё в конце 1990-х, когда стало очевидно, что шаблоны C++ имеют колоссальную выразительность, но практически не дают средств для описания намерений программиста. Шаблон можно было инстанцировать почти с любым типом, но ошибка проявлялась либо в виде километров сообщений компилятора, либо в виде неожиданного поведения в рантайме. Уже тогда Страуструп сформулировал проблему как «отсутствие контрактов для шаблонов», когда программист знает, что от типа требуется оператор + или ==, но язык этого не выражает.

Ранние предложения концептов были чрезвычайно амбициозными и стремились описывать не только синтаксис, но и семантику. Например, концепт EqualityComparable должен был означать не просто наличие operator==, но и выполнение математических свойств эквивалентности: рефлексивности, симметричности и транзитивности. Аналогично, концепты для упорядоченных типов предполагали строгую слабую упорядоченность, а для итераторов корректное поведение при многократном проходе. Это отражало академический взгляд на обобщённое программирование, сильно вдохновленный функциональными языками и работами Степанова.

Читать далее

Нескучное программирование. Ограничения

Уровень сложностиПростой
Время на прочтение12 мин
Охват и читатели18K

В языке C++ перегрузки функций и шаблонов исторически были и остаются мощным инструментом для выражения различных реализаций одного и того же интерфейса. Многим перегрузки видятся как удобный способ дать одно имя разным функциям, но на практике понимание того, как компилятор выбирает нужную перегрузку, может стать источником ошибок и недоразумений. Компилятор же руководствуется сложным набором правил, которые мы ему предоставили, учитывает не только типы аргументов, но и порядок специализаций, преобразования типов, const-квалификаторы, шаблонные параметры и многое другое. А ошибки, возникающие при перегрузках, часто трудно диагностировать, поскольку сообщение компилятора может ссылаться на глубоко вложенные детали реализации вместо очевидного исходного кода. Об этом была предыдущая статья...

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

Давайте теперь поговорим о том, что именно делают ограничения (requires) в современном C++ и почему появление этого механизма стало таким важным шагом в развитии шаблоннов. Тут надо сделать немного шаг в сторону и вспомнить, что исторически шаблоны в C++ были мощным, но довольно опасным инструментом, еще одним языком в языке, на котором можно было сделать почти всё, было бы желание. В итоге компилятор позволял подставить или подхачить любой тип, а проверка того, «подходит ли он на самом деле», откладывалась до момента инстанцирования, что нередко приводило к ошибке далеко от места вызова, а сообщение о непосредственном месте ошибки превращалось в многостраничный отчёт о внутренней кухне компилятора и как он работает с шаблонами. requires меняют эту модель, позволяя описывать ожидания от типа явно и прямо в объявлении функции или класса.

Читать далее

Нескучное программирование. Overloads

Время на прочтение20 мин
Охват и читатели14K

Года четыре назад, на стыке двух проектов, когда старый уже просто сапортили, а новый только находился в стадии препродакшена и питчингов разной степени завершенности (планирование и попыток продать концепт и идеи незаинтересованным инвесторам) у моей тогдашней команды удивительным образом появилось свободное время и где-то между обучением новичков премудростям кастомного движка, попытками переключаться на 20-ый стандарт и ретроспективой бэклога, солнечным сентябрьским утром родилась идея сделать студийные обсуждения в стиле подкаста PVC по теории С++, чтобы понять какие возможности реализованы в движке, какие компетенции есть у пополнения и вообще как-то освежить теорию. Так родился мини-курс внутристудийных лекций от разных людей с разным, но реальным опытом применения, позже осевший в местной вики в виде набора статей, бест практис или вообще заметок с упором на игродевовскую тематику. Чтобы все это добро не пропадало, ибо человекочасов туда было вбухано порядком я решил эти заметки облагородить и выложить в читаемом виде (видео к сожалению не будет, ибо НДА и всяческие спойлеры проектов и местной кухни разработки, да и никто не будет эти десятки часов болтовни слушать), но сами принципы языка и его особенностей вещь копирайту неподвластная, поэтому в таком виде вроде можно. Если подобный формат "зайдет" аудитории Хабра, можно будет продолжить статьи в виде небольшого цикла, как это получилось с серией Game++. К сожалению, начнем не с обобщенного программирования, а со второго подкаста про перегрузки, потому что первые записи оказались испорчены и на их восстановление потребуется время. Итак перегрузка в С++, не так как её учат в универе и дают в книжках...

Читать далее

Не паникуй, ты просто попал в AA+ игрострой

Уровень сложностиПростой
Время на прочтение10 мин
Охват и читатели15K

Эту статью я написал лет десять назад, когда только попал в большую студию EA SpB. И забыл бы про нее, но недавно проводил ревизию заметок и набросков на старом HDD и решил, что она до сих пор актуальна, разве что цифры выросли. Тогда проекты под миллион LoC казались гигантами, наверное это и сейчас очень много, но теперь это это просто код движка. Но суть не изменилась, просто цифры выросли.

Помню тот день, когда я впервые сел за рабочий стол в офисе, а до этого делал другие проекты и кодовая база размеров 100к строк вместе с либами, движком и логикой казалась - ну очень немаленькой. А тут скачал репозиторий, открыл идеешку, и она минут на пятнадцать подвисла на индексировании файлов. Я смотрел на всё это безобразие и думал: «Это нормально? Мне дали самый отстойный джунский комп? Я что-то сломал уже на онбординге? Мы все умрем?» Нет, всё было нормально, просто я впервые столкнулся с промышленной кодовой базой большого проекта.

Команда в тот момент выкатывала мажор Sims Mobile, который зафейлили почти на месяц и, честно говоря, на нормальный онбординг ресурсов просто не было. ПМ выдал мне простую задачу на разгон, так сказать, чтобы стулья в редакторе дома сохраняли свое положение и размер между запусками, потому что они, как вы наверное догадались - этого не делали и оказывались в дефолтных точках спавна. Звучит элементарно, правда? Сохранил координаты в конфиг, прочитал при старте и таска готова. Вот только я понятия не имел, где искать код этого сохранения конфига, объектов, как называется класс, где лежит конфиг и сами стулья, и есть ли вообще система для таких вещей или надо писать с нуля. Небольшой спойлер, системы не было, все объекты в доме всегда спавнились в тех точках, где их поставил дизайнер, т.е. для редактора дома сейва не было, а для игры был.

Добро пожаловать в семью

Мифы, суеверия и народные мудрости в разработке игр

Время на прочтение23 мин
Охват и читатели14K

Существует довольно много распространённых «мудростей» о разработке игр на C++, различных обрядах и видах магии. И как это часто бывает с подобными сакральными знаниями, при внимательном осмотре - у части действительно есть право на жизнь, часть можно отправить в Каирский музей отбирать славу у мумий, а часть вообще оказывается родом из чужой реальности, и работать как предполагалось отказывается. Но это не мешает некоторым компаниям относиться к таким советам как к скрижалям, бережно принесённым с великой горы совещаний. Новым сотрудникам их передают почти с торжественностью обряда посвящения: «Так делали наши предки, так делаем и мы».

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

Понедельнишное

Зоопарк строк в вашем C++ коде?

Время на прочтение26 мин
Охват и читатели27K

CryEngine2 использовал класс собственный CString для реализации работы со строками и немного использовал строки из стандартной строковой библиотеки Windows. Насколько я помню, последняя версия CryEngine всё ещё использует те же самые CString, она кардинально поменялась внутри, но как дань истории название класса менять не стали, зато сильно расширили функционал. Я не на 100% уверен, применялся ли CString только в редакторе или в рантайме игры тоже, вы можете сами это посмотреть в исходниках, которые все еще доступны на гитхабе. Это один подход к работе со строками, довольно распространенный в мире игростроя - когда мы все нужное пишем сами, не оглядываясь... хотя, тут больше уместно слово поглядывая, на существующие реализации и утаскивая в проект все самое лучшее.

Есть и другой подход... Я работал в команде над некоторым проектом, который должен был выйти на консолях, и в какой‑то момент на проект пришел эффективный тимлид, который хорошо умел в красивые презентации, и продавил использование std::string из sdk. Все очень опытные программисты, синьоры и руководство важно кивали на совещании и согласились всё перевести на std::string… не такие уж они оказались опытные, как выяснилось. В итоге мы заменили большую часть CString на std::string. Не сказал бы, что это сильно повлияло на время компиляции — плюс‑минус минута к проекту, который собирается двадцать минут, особой погоды не делают, но это также превратило наш довольно понятный базовый код в запутанный кошмар. Возможно, для переносимости это было лучше, но ни наш проект, ни CryEngine2 Editor так и не были портированы ни на Linux, ни на какую‑либо другую платформу.

Прошло десять лет, я вижу ровно туже ситуацию на текущем проекте — новый тимлид решил перевести местный MySuperPupeString на std::string, уже предчувствуя «нижней чуйкой» последствия — запасаюсь попкорном и беру отпуск на следующий месяц после принятия решения. Но не это интересно, а то — какие вообще строки могут быть в вашем с++ коде.

Строка, на строке и строкой погоняет

Хороший, плохой, цветной и быстрый

Уровень сложностиПростой
Время на прочтение13 мин
Охват и читатели14K

Давным-давно, когда с ездовым котом приключилась "записка шестая", а знания об аллокаторах и опыт их применения ограничивался линейным и системным, перебросили мою команду в помощь другой команде, которая занималась системами навигации больших судов. Ездовые коты, особенно нестарые - это такие создания, которые редко изучают документацию детально, а чаще бегло читают там про интерфейсы систем в проекте, malloc, new, системные аллокаторы и думают, что теперь-то точно понятно, как всё устроено. А потом приходит работа и такая: “Забудь всё, что ты знал. Ты не дочитал до страницы восемьсот что-то там РД, тут есть свой аллокатор - и он реально плохой”.

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

А вот почему нужны и важны ненормальные - объяснений почти нет, как и самих реализаций в открытом доступе. В этой статье я расскажу, какие повстречал ненормальные алгоритмы распределения памяти, чем они живут, кого едят, и почему иногда malloc делает вид, что он не при делах и таки да, malloc может возвращать null и ту проверку мы убрали зря.

Читать далее

Сам себе breakpoint

Уровень сложностиПростой
Время на прочтение15 мин
Охват и читатели18K

Когда отлаживаешь программу, речь идет про использование отладчика в студии или другой IDE, то почти всегда имеешь дело с точками останова (breakpoint, бряками) — механизмом, когда выполнение программы приостанавливается, чтобы можно было заглянуть внутрь и понять, что происходит. Точек останова есть всего два основных типа, программные и аппаратные, а остальные все сделаны на их основе. Эти два базовых типа могут вести себя похоже, но устроены по-разному.

Программные точки останова — это то, с чем сталкивается каждый разработчик, когда вы ставите красную точку в среде разработки (в основном я использую большую студию) или используете команду bp под WinDbg. В этом случае отладчик просто подменяет один байт машинного кода в нужной инструкции на команду int 3. Это специальная инструкция для вызова прерывания отладки (Debug Interrupt), имеет машинный код 0xCC и говорит процессору: “Остановись, я хочу передать управление отладчику”, соответственно когда выполнение доходит до этой инструкции, срабатывает прерывание, и управление передаётся в отладчик. Отладчик "просыпается" и видит, что программа остановилась из-за исключения EXCEPTION_BREAKPOINT , возникшего по конкретному адресу, проверяет свой внутренний список точек останова и находит ту, которая была установлена по этому адресу.

Читать далее

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

Время на прочтение14 мин
Охват и читатели19K

В 90-х и 2000-х студия Impressions Games выпускала отличные исторические градостроительные симуляторы. Я играл во все игры этой серии от незабываемого Caesar 3, который вообще был первой моей компьютерной игрой на отцовском компуктере, до Императора про древний Китай. Но египетский Pharaoh и греческий Zeus запомнились намного четче, но вот почему я сказать не берусь.

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

Ностальгии пост и много скриншотов

Я отклоняю комиты с использованием кучи и прошу коллег переписать такую логику

Время на прочтение11 мин
Охват и читатели49K

Хочу поделиться своим опытом разработки крупных игровых проектов на C++, где производительность и стабильность — это не просто приятные бонусы, а абсолютно естественные требования к разработке. За годы работы над движками и играми я понял, что подход к управлению памятью очень сильно влияет на весь проект. В отличие от многих приложений - игры, особенно большие, часто работают часами без прерываний и должны поддерживать стабильный фреймрейт и отзывчивость. Когда проседание fps или фриз происходит на глазах у сотен тысяч игроков, вам уже никто не поможет — ущерб уже нанесен, а в steam полетели отзывы о кривизне рук разработчиков.

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

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

Читать далее

Blackbox gameplay

Время на прочтение10 мин
Охват и читатели1.6K

В конце 90-х, в эпоху таких игр, как Caesar III, Pharaoh, Stronghold и Zeus: Master of Olympus, если вы не знали, то отцом всех этих игр был Simon Bradbury (хотя в Фараоне и Zeus скорее только крестным), начала набирать популярность идея упрощения пользовательского интерфейса. Во многом это было ответом на критику, что перегруженные UI отпугивают широкую аудиторию (и это действительно так, адепты Евы не в счет), надо было как-то привлечь людей помоложе, которые ни тогда, ни сейчас не отличались желанием глубоко вникать в механики. На этом фоне начали сознательно скрывать сложные внутренние механики (black box gameplay) от игрока — в том числе в градостроительных стратегиях.

Уже в Caesar III (1998), хоть та и имела отличную визуализацию потребностей домов и цепочек производства, всё же оставляла за кадром множество числовых значений: точное количество работников, занятых в зданиях, внутреннюю очередь обработки запросов, приоритеты в распределении ресурсов. Игроку приходилось догадываться о многом опытным путём и считать на бумаге параметры райнов и рисовать цепочку распределения товаров. Сравните это с мануалами Age of Empires II, где на сотнях страниц подробно разбирались все коэффициенты.

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

Читать далее

Информация

В рейтинге
11-й
Откуда
Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность

Специализация

Десктоп разработчик, Разработчик игр
Старший
От 300 000 ₽
Git
C++
Многопоточность
Прикладная математика
ООП