Как стать автором
Обновить

Комментарии 16

В юньке появились Span и и стандартные парсеры с его поддеркой. Мне в очень многих местах получиось убрать выделения памяти.

Вы не путайте личную шесть с государственной, то появилось в Mono и позже, это отдельная боль была, потому что по факту было две копии строки - одна в моно и одна в редакторе. В 2014 году не то что std внутри не было, там даже не все "велики" вроде TArray работали нормально.

Всё это, конечно, интересно, но непонятно самое главное - зачем нужны строки в играх и особенно их сравнение. Я делал игру, там с NPC можно взаимодействовать посредством ввода текста и сравнение строк нужно. Но других таких игр я не помню со времен спектрума (там были The hobbit и Gremilins и не сказать, что они много места занимали).

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

Вот так выглядит конфиг карты в UE

Begin Map
   Begin Level
      Begin Actor Class=StaticMeshActor Name=787_chairs_economy_10 Archetype=StaticMeshActor'/Script/Engine.Default__StaticMeshActor'
         Begin Object Class=StaticMeshComponent Name="StaticMeshComponent0" Archetype=StaticMeshComponent'/Script/Engine.Default__StaticMeshActor:StaticMeshComponent0'
         End Object
         Begin Object Name="StaticMeshComponent0"
            StaticMesh=StaticMesh'/Game/Meshes/B787/Chairs/787_chairs_economy.787_chairs_economy'
            StaticMeshDerivedDataKey="STATICMESH_34081786561B425A9523C94540EA599D_359a029847e84730ba516769d0f19427_08B81D3F4753513B93E720832A7E9708000000000100000001000000000000000000803F0000803F00000000000000000000344203030300000000"
            bHasCachedStaticLighting=True
            VisibilityId=100
            BodyInstance=(Scale3D=(X=2.540000,Y=2.540000,Z=2.540000),bAutoWeld=False)
            RelativeLocation=(X=0.000200,Y=-415.462006,Z=540.482971)
            RelativeScale3D=(X=2.540000,Y=2.540000,Z=2.540000)
            CustomProperties 
         End Object
         StaticMeshComponent=StaticMeshComponent0
         RootComponent=StaticMeshComponent0
         Layers(0)="Chairs"
         ActorLabel="787_chairs_economy_10"
         FolderPath="Chairs"
      End Actor
   End Level
Begin Surface
End Surface
End Map


Вот нераспакованный левел того же UE

Вот левел из CryEngine, не помню уже какой ревизии, чтото было на харде

objects = create_section {
}

objects_base_params = create_section {
	version = 0,
}

bbox = create_section {
	bmax = create_section {
		1,
		9.516,
		146.429,
		1,
	},

	bmin = create_section {
		-135.448,
		-30.102,
		0,
		0,
	},
}

dtool = create_section {
}

dtool_base_params = create_section {
	version = 0,
}

Неудобно хранить и работать с бинарными данными в редакторе, во первых не отследить историю изменений, потому что все более-менее нормальные VCS рассчитаны на текстовые данные. Во-вторых если сломали левел, то текст, usd, lua, json, кастомный текстовый формат починить намного проще, чем откатывать и фиксить бинарь. Бинарные данные это для релиза, когда уже все проверили и надо быстро это грузить

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

Ага, есть два подхода для таких парсеров, для текста как выше, он же парсер, он же writer, он же чекер и в 99% он текстовый, но умеет сейвить бинарную версию. Для реализа, отдельный ридер для бинарного формата, который только и умеет что читать его, но быстро. Но этот подход лишён возможности патчить релизные бины. Второй подход это текстовый формат, который позволяет накладывать патчи, и пусть он немного медленнее в чтении, зато намного удобнее в работе. Вы можете мержить два конфига, удалять или добавлять новые поля отдельными патчами, как это делает гит, и что самое важное делать это рантайм или на загрузке игры. С бинарными конфигами это на порядок сложнее делать, я не говорю что невозможно но проблем будет много. Это было одним из критериев, почему в симсах был выбран именно такой формат данных

спасибо, стало немного понятнее

Скорее нет, статья больше про механизм "string interning", но пересечений с железом много да, на консолях мы тоже недалеко от железа. Ту статью я посматривал в процессе подготовки материала, как и другие - ссылки в конце статьи. Вас наверное смутили картинка и примеры?

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

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

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

насколько я понял, это компилятор так обрабатывает макросы - в макросе строки существуют, а в сгенерированном коде - нет. в С++ так не будет, т.к. макросы - по сути чисто find-and-replace строк, а в nim (я так понимаю так же как и в zig) это код, который выполняется во время компиляции отдельной стадией

Самая лучшая оптимизация работы со строками - не использовать строки. Вместо них enum в коде. Как вариант можно использовать очень короткие строки с длиною до 8 байт - такие можно в один uint64_t запихать. В том же Doom, помнится, имена ресурсов в WAD файле как раз 8-байтные были и этого было вполне достаточно.

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации