Comments 35
очень поверхностно
Это открытая площадка и у Вас всегда есть возможность написать детальный разбор. Я здесь и не ставил целью приводить схемы и графики. В минусах есть соответствующий пункт
когда идёт обсуждение конструкций на основе слов - теории, тоесть повествует разработчик, и разработчик даёт маленькие примеры, а все доводы сводятся, высотой то получается возможно у вас приоритеты просто другие, но на деле есть ОС(разные ос бывают, разный диспетчер и набор возможностей) - компилятор(разные компиляторы по разному что-то там делают в итоге) - окружение - настроеный проект - пример/примеры, иначе для кого вы повествуете и показываете маленькие примеры? всё разрозрено получается, нету пруфа - конечного примера с примерами. Да понятно, что вы хотите так рассказывать, но вы же говорите про сложные системы, а не про Hello World, и метод пересказал тут к сожалению не работает, тут побольше показывать надо
например если говорить о текстовом редакторе на словах он сводится к созданию текстового буфера только и всего, к сожалению просто произнести если мы хотим еффективно потратить время, не достаточно, и приходится показывать пример, и там уже можно какие-то концепции показать, когда мы задаёмся такими вопросами, и есть пример, и в нём углубленное что-то это может углубить приблизить к пониманию, в тот же момент просто проговорив теорию, это никак никуда не углубляет, ну типо ну да и что такой еффект, в этом и прикол, когда человек подкрепляется такими микро запросами он может сформулировать то с чем он столкнулся на примерах, а тут маленькие примеры кругом, и они далеки от всё еще примеров, но более комплексных
А всё общение - это конструкции на основе слов, другого пока не придумали. Не всем интересно, а иногда и скучно, читать углубленные технические детали и код (которого полно на работе, а на Хабр приходят чтобы отдохнуть, а не работать), тем более что часто приводимые технические решения нельзя применить без серьезных доработок, даже если выложены полные исходники. Да и читать плюсовые исходники и разбираться, что там автор понаписал - то еще удовольствие и задача скорее техревью, а не таких текстов. Но не зная определенных подходов или опробованных решений вы будете вынуждены повторять все те ошибки, которые уже были совершены до вас, вместо того чтобы поискать решение на гитхабе или других ресурсах, возможно пейперах или статьях. Ну выложу тут исходники хаос аллокатора - серьезно думаете кто-то будет их смотреть и применять, я сам его использовал последний раз 15 лет назад на паре проектов и больше не хочу.
понял вас, нет решенное не интересно, интересно когда можно почитать - попробовать, вот найдите новичка(разраба) в геймдеве совсем зеленого, расскажите ему в стиле вашей статьи что-нибудь, и вот если если он будет чуть смелее он будет вам задавать вопросы те какие у людей в ВУЗах аля зачем это всё нужно, и там вопросы могут не задать, а вот если вам человек задаст эти все вопросы и что и почему - это даже лучше будет, как я понял вы опытный человек просто и у вас приоритет на ингридиентах, когда у новичков вопросы в целом, ну да можно отправить на курсы, и на книжки, но вопросы будут без ответов всё равно, так и выходит кто-то показывает на примерах в интернете и понимает этот нюанс, а кто-то рисует слайды и картинка только на слайдах
тоесть кем вы себя позиционируете (я с вами давайте погружаться) или вот смотрите слайды и есть курсы
эти 2 способа повествования разные, нельзя точно сказать что лучше или хуже, но смотреть как человек новичек рассказывает о своём пути как он сделал клон майнкрафта интересно, чем как аллоцировать инстансы, и картинки там дальше не предпологается там или слайд или сухой отчет
вот есть какие-то видео уроки прям я видел по свету, так там одна наука и слайды и редкие картиночки, или оглдев, который в своём стиле, но пытается придерживаться обзора ситуации, потомучто это многоуровневая ситуация
частично 3д и игры похожи на скульптуры, так если скульптор не лепит с учениками, как можно понять что мы лепим(только дедуктивно, но плоскость скульптинга не в дедукции ), ну словами можно сказать например лепим кубик и всё дальше все лепят как услышали
прямо-таки очень?
Jijiki, я вас умоляю, не поверхностно, а достаточно для такого рода статьи.
Например, по приведенной в статье ссылке на репозиторий с TLSF содержится ~1K loc на сях. Сферическая публикация с его описанием — это простыня не менее чем 30+ страниц A4, забитых формулами и ссылками на Кнута + пара десятков строчек сишного псевдокода. И все это добро не даст новичку полного понимания для самостоятельной реализации, а через месяц после прочтения — напрочь выветрится из головы.
Тут же вопрос, надо ли это автору и читателям, когда более углубленный материал уже несколько раз написан другими людьми? Чтобы пацаны с уважением головами покивали и некоторые в закладки добавили да забыли насовсем, ибо повод и целесообразность применения может совсем не появиться?
это звучит так будто делать движок и 3д игру нереально без движка. Ладно я понял
то что в книжках, это не совсем то, что нужно, там новичкам если такие есть надо буквально пару нюансов показывать, и тогда всё встаёт на свои места, а так можно ходить вокруг да около, там после этих нюансов будет видно, что изучать и прочее, а в книжках показывают просто общие моменты базовые, тоесть всё еще вводная, тоесть и приоритеты и акценты другие
хотя наверно, мы все об одном и том же пишем, возможно, оно видно это даже на видео синк матрикса, но просмотрел я эти нюансы далеко не в его роликах
если вам написать что для игры нужно дерево(одно и второе, возможно третье) то пока еще же не понятно как через дерево уловить принцип
ниразу не видел обзоров кстати об этом, у синк матрикса и сиплюсплюсгая, еще проще примеры где суть теряется за длинной кода
это звучит так будто делать движок и 3д игру нереально без движка.
Нет, это звучит как «данная статья обзорная и в ней приводятся интересные истории о применении разных аллокаторов для разных задач, детали их реализации со всей выкладкой и обоснованием конкретных решений в ней будут лишними — для этого надо писать совершенно другие статьи с другой мотивацией и посылом, а иногда еще с нотариально заверенным разрешением от юридического департамента».
Когда вы пишите движок/игру, вам эта статья (да и вся их серия) может помочь, как вдохновение, источник идей или навигатор по нескольким специфичным аллокаторам, а за реализацией — добро пожаловать в гугл, искать нужный учебник/руководство/вайтпейпер/etc., параллельно воплощая все это в коде.
тогда, std::string - ура я создал строковый буфер да еще с деструктором, С об этом может только мечтать, так в учебниках нету инфы как раз по краеугольным моментам нюансам, там только общие моменты, наверно лучшая из них будет только Седжвик, вот возьмите Седжвик алгоритмы и структуры данных и пишите движок свой.
простите но вы не правы, в контексте игр, без примеров и прочего не уложиться
тут не столько играет планка автора, сколько то что обсуждаем, и нету пруфа, а значит поверхностно выходит(ведь нет смысла показывать примеры сцен - обсуждаем же аллокатор(в контексте геймдева), игры, в конце концов писать статьи с обзорами не должно быть работой после работы наверно), так вы меня отправили в интернет пойду пожалуй )
я вот сделал себе фулл тест пример оконченный, могу рассказать о нюансах
Скрытый текст

там вон еще пенумбра модная, ну или просто тень прозрачная и при том при всём еще глобал свет )
могу рассказать о нюансах
Вам несколько раз предлагали вместо вот этого оффтопа в комментах оформить ваш опыт в виде большой и основательной статьи. Предлагали без задних мыслей и желания подколоть. Будет круто, если вы так и поступите, т.к. темы, которые вы затрагиваете, гораздо интереснее, чем очередные пассажи от ЛЛМ о создании Сапера/Змейки на питоне.
материала очень много накопилось, там видно будет
Не кормите тролля, почитайте его комменты - доминирующее большинство это наброс известной субстанции на вентилятор.
насчет пайтона вы поторопились, он нужен будет для своего формата, а сапёр это там в конце написано генерирует полости, но полости надо превращать в heightmap(потому как в блендере неудобно делать пещеры) а он плоский или закрытый если это пещера и если пещера с потолком
полости надо соединять и выдавать им логическую высоту чтобы пещера была пещерой
еще нужен кеш геометрии, вот почитайте что автор пишет, 100 моделек с костями грузят систему, соотв это 1 моделька(родитель инстанс), кеш должен запомнить все движения модельки и не считать после первого раза
как это связано с пайтоном? или с fbx, очень просто в случае fbx это SDK или assimp в случае своего формата, перенос модельки скриптом, и запоминание условно синуса, но не просто синуса а тех кривых в пространстве котором анимация
у анимации 2 или 3 подпространства и вот чтобы не считать нужен кеш
соотв знакомиться с этим через пайтон прям в блендере с документацией ну и так далее
а на поверхности да, просто сделали модельку, сделали риг и всё, по-сути честно всё, и так повторить 100 раз образно
Куча памяти, которую мы выделяем, живет всего один кадр.
А что именно? Можно примеры, под что выделяется память каждый кадр?
String(framemem_ptr()) вас устроит? Вот пример прям из рабочего проекта.
а вы в заключении расплывчато это сформулировали как понимать это тоже не ясно, тоесть оптимизируем или не знаем? как бы иду по вашей логике строки нужны и аллокатор тоже, но нет определённости с выделением строк в фреймтайме, просто когда нет определённости сложно сказать как можно попробовать, чтобы снизить выделения памяти на строки
какие строки уточните пожалуйста, квест буки или просто текст или текст в мире, какая кодировка, возможно там еще юникод код есть, еще зависит от ОС - платформы, и еще зависит от графического стека - апи, но ситуации чуть-чуть схожи, но определённости просто нету
а вообще сий пазл заключается в следующем, тоесть надо поиграть в игру, как нарисовать текстуры без строки, тоесть по обращению к кешу символов прям напрямую, и части текста загонять выделив память под строки, эта ситуация зависит от набора Локали если это юникод и есть система локализации, но ситуация такая да, тоесть в базу данных можно прям строки гнать, а если не хочется выделять в фреймтайме обращаться напрямую к глифам и рисовать как-то наверно
потом еще вспомните есть 2 подхода в кодинге
1 if
2 map
вот можно все случаи выделения превратить в прямую обработку по обращению к кешу иначе придётся выделить строку или последовательность, соотв лучше перед игрой выделить нужные строки, а те глифы числовые или еще какие либо выделять, либо напрямую рисовать без выделения
тоесть 2 числа это будет указание 2 чисел, которые в кеше возьмут 2хтекстуру(тоесть надо напрямую взять эти глифы) еще возможно есть ситуация передать или запаковать это в текстуру - тоесть текст превратить в текстуру и рисовать по uv их, ну как анимации в текстуру запаковывают, так же и текст можно загнать наверно в каком-нибудь гудини возможно
кстати можно снизить выделения на строки до минимума кустарными способами,
1 при входе в игру создавать текстуры, сохранить имя персонажа как строка, тут же и генерируются квестбуки
2 числа оставить можно как есть и вот тут есть механики, например компас убирает частично числа, время это обновление 1 раз в минуту, скорость тоже механика - спидометр, всякие кулдауны - бар загрузки, не числами можно отобразить, если принципиально уходим от чисел можно урон цветом рисовать
итого выходит вся менюшка сгенерена в текстуру, большая часть текста в текстурах, там буквально нано числа остаются, потомучто без кулдаунов нет игр
String(framemem_ptr())
мне, к сожалению, это ничего не говорит. Для игрока это что? Какая игровая сущность создается и уничтожается каждый кадр?
тут скорее всего подарзумевается или UI или еще что, но все неясные ситуации со стрингом ведут в С в текстовый буфер, и после этого вопросы должны исчезнуть, потомучто под катом std::String эта ситуация, тоесть строка это буфер символов скорее всего, его надо выделить до цикла того размера каким он должен быть,
to::string() без подготовки поидее перевыделяет память, но тут ситуация, цена заключена не в перевыделении на самом деле, а в получении чисел, тоесть строка число, и это вроде удобнее чем sprintf() и курсивом ловить места, С++ даёт возможность разбивать строки и части делать текстурой сразу, часть просто гнать в строку
поидее плата за строку может ощущаться на std::u32string - но тут и плюсы, можно настроить локализации и добавить емодзики
Это строка, которая выделяет память через фрейм аллокатор (разновидность линейного аллокатора, который сбрасывается в начале фрейма). Т.е. такие строки очень дешевые, вы их можете создавать сотнями и тысячами без какого-то существенного влияния на время кадра. Например вы захотели проийтись по сцене и собрать типы и имена юнитов для каких-то своих нужд, это работа со строками, если вы будете использовать обычный std::string, то это приведет к большому числу аллокаций памяти, которые не нужны. А тут мы знаем что эти данные не живут дольше одного фрейма, мы их собрали обработали и вывели в консоль или файл. Это один пример.
Второй пример - это дебаг AI. Есть BT (дерево поведения), оно определяет как себя ведет юнит в данный момент, какую отрабатывает атаку, или прыжок или другое действие. Никакого более удобного способа сериализации состояния БТ кроме строки, которую можно положить в буфер и потом распарсить - игрострострой не придумал. Теперь имеем 30-50-100 и больше объектов на уровне, каждый с запущенным БТ и каждый фрейм может сработать в одном дереве до 100 нод (надо проверить что враг на дистанции, что есть оружие, что выполнены подходящие условия для действия) - каждый вход-выход-проверка в ноде это отдельная строка, которую надо собрать, обработать, отфильтровать и сохранить для дальнешей обработки игровым дизайнером. Если вы будете делать это через стандартный аллокатор, то получите 1 фпс, возьмете самый быстрый TLSF - 10 фпс, но играть на 10 фпс очень сомнительное удовольствие - и дизайнеры вам об этом скажут непременно. Поэтому вы берете самое быстрое что у вас есть, фреймовый или линейный аллокатор и начинаете на нем строить вашу систему отладки ИИ.
т.е. это всё для отладки и в прод не пойдёт?
ну и совсем дилетантский вопрос, почему нельзя просто выделить char[99999] и писать туда, а на следующий фрэйм сбросить указатель в начало и снова писать туда?
что-то для отладки, что-то в прод (например телеметрия разная, где и что вы на экране нажимали, каких монстров убивали и в какую часть уровня ходили). Опять же лог надо писать и гдето его сохранять, чтобы отослать в случае краша. Ок, мы выделили буфер для условно одной системы (ИИ), для другой (телеметрия), а для третьей, четвертой и дизайнерской тоже придется делать отдельные?
тоже придется делать отдельные?
Если не хочется отдельные, можно писать всё в один. Ставить в начало записи символ, который нигде не используется, чтобы по нему разделять, потом какой-нибудь идентификатор. Например, текст начинающийся с $a - про ИИ, с $b - телеметрия и т.д. Потом же вы всё равно сбрасываете это в файл, не онлайн смотрите? А текстовый файл можно сплитануть по этим $ каким-нибудь питончиком и собрать из него какой нужно выходной файл. Можно, например, всё html тэгами раскрасить и подсветить и гиперссылок добавить.
Скрытый текст
очень упрощенно вы про это?
template<typename T>
void SomeTree(const SomeNode<T>* root)
{
if (root == nullptr)
return;
//вошли пошла строка .... подготовили тут строка да?
// Обработка левого поддерева
renderTree(root->left);
// объект
const T& obj = root->object;
////чото случилось в логике пошла строка .... подготовили тут строка да?
// Обработка правого поддерева
renderTree(root->right);
}
тогда есть подозрения что все строки надо приводить к некому формату, и кидать строку тогда куда-то наподобии в sprintf() и ниче не парсить наверное, вообще спасибо что написали что вы делаете есть о чем подумать
в текстовом редакторе так же, где есть желание вывода статусной строки, и там ниче лучше я не придумал на С кроме как кидать строку тупо в sprintf, всё остальное какая-то эквелибристика, как мне показалось никакие байты там не выйграть, что у вас по таймингу или в любое время сработает, что в текстовом редакторе курсор может ходить может не ходить (такая строка где линия активная, имя файла, и позиция курсора например - изменяемые данные )
main.c вот можете посмотреть если будет интересно
100 обьектов костной анимации да?
и еще вопрос тогда а в дереве обьекты у вас указатели или вариейбл?
работать с указателями может и не безопасно, но если от хранилища обьектов брать указатели может будет какой-то прок
если игра сандбокс, надо выгружать обьекты которые не видны и каким-то образом закарикатурить их действия(возможно есть хитрые алгоритмы с таймером и предугадыванием или просчетом действий по графу тоесть( деактивация когда игрок вне поле зрения далеко совсем, скип действия пока спит по графу ) и когда игрок на подходе активация и установка действия (спал спал и +1)текущего ), надо снять нагрузку если возле игрока не 100 обьектов костных например со своими скриптами
и мелкие моменты, например убрать sqrt из дистанции и смотреть по точке - ААББ
вообще тут нужны отсечения по состоянию графа, тоесть нельзя линейно идти по всем обьектам наверно еще, тоесть чисто на евентах и отсекание (если нода отсеклась по дистанции все активные скелетки уходит в сон(это карикатурное выражение их нельзя просчитывать это очень дорого, но статусы надо хранить как-то))
https://godbolt.org/z/ETEx6G8hc а так пробовали? формат только добавить и раскидать в каждой строке по 40 символов, суть в том что читаем по очереди, а пишем в реалтайме наверно
тоесть обьекты пишут так как произошло срабатывание какое-либо и регистрируют структуру в очередь, а читаем в тот момент когда доступно(вобщем из очереди), и раз это дебаг, то можно и выделить память зараннее под дебаг
Абсолютно непонятна идея "Плохого" (рандомизирующего) аллокатора.
Любой код в программе, использующий динамическую аллокацию, в праве расчитывать, что между аллокацией и деаллокацией блок памяти доступен под известному фиксированному адресу.
Перемещение уже выделенных блоков аллокатором приведёт только к одному - провисанию объектов и прямой порче памяти.
Как вообще возможно такое поведение аллокатора?
MISRA C:2012 Rule 18.6 (https://www.mathworks.com/help/bugfinder/ref/misrac2012rule18.6.html) "The address of an object with automatic storage shall not be assigned to another object that may persist after the first object has ceased to exist"
Т.е. нельзя хранить адреса на чужие компоненты. Хотя это правило касается автоматической памяти, тот же принцип применяется к динамической памяти - нельзя хранить указатели, которые могут стать невалидными. Какой указатель может стать невалидным в кодовой базе на 2М loc? А тем более еще и не на своих компонентах и либах, это еще один инструмент отладки и тестирования (как и ASan и ему подобные), но который специально создает стрессовые условия для выявления скрытых багов. Если вы каким-то образом смогли выделить, получить или сохранить сырой адрес, то в какой-то момент это "рванет", лучше пусть "рвется" на тестовом стенде. Ну вот пример - простой, вы получили const char* объект, насколько это невалидное поведение?
Стало ещё непонятнее.
Приведенное вами правило MISRA не содержит ни слова о динамической аллокации. Там вполне понятное и логичное правило, вытекающее из известного lifetime переменных с automatic storage duration.
В случае динамической аллокации lifetime выделенной памяти тоже известен: от момента выделения до момента освобождения. Аллокатор не имеет права превносить какое-либо творчество в это процесс. Если у него кто-либо попросил память - значит она нужна, и может быть использована.
И "рванёт" ваш код не только у того, кто получает сырые указатели, а в том числе и у того, кто абсолютно легально владеет объектом, выделенным в динамической памяти.
Аллокатор использует собственную таблицу трансляции адресов. Можно хранить Hх адреса, нельзя хранить производные и косвенные адреса на их основе, которые перестают быть валидными при выходе из блока, который запросил работу с этим адресом. pdx::memcpy(H3, H1, 10) будет работать,
pdx::memcpy(H3 + 5, H1 + 5, 5) соответсвенно сломается.

копирование части аллоцированного блока - валидная операция, причём как для владельца объекта, так и для получившего сырую ссылку. Как вы их собрались различать?
memcpy - не единственный способ обращения к памяти, это мягко говоря. Я бы даже сказал, что это какой-то краевой случай.
В общем, кажется, что выглядит это примерно так: "мы тут, зная, что у нас есть вот такие code style guidelines (использовать memcpy/memcmp/...), и зная, что они более-менее соблюдаются, решили что-то очень сильно сломать в коде, чтобы сломалась куча корректного кода, но которого у нас вроде как не должно быть". Какая-то очень узкая заточка на специфику проекта.
Вы правы в своей оценке, различение владельцев через анализ операций копирования действительно выглядит как переусложнённое решение, но рамках разработки ECDIS-систем (не знаю как сейчас, но врядли кардинально изменилось) динамические аллокации запрещены и сама проблема некорректного копирования аллоцированных блоков снимается архитектурными ограничениями. Memcpy и подобные ему операции действительно лишь симптом, а не причина проблем с владением, но позволяет найти это проблемы до прода, который чаще всего в море и сделать мы там ничего не можем.
Хороший, плохой, цветной и быстрый