На сколько большие могут быть структуры и таблицы
На сколько большие могут быть структуры? Я имею в виду есть ли какой то лимит по параметрам у структур за который не следует переходить? Например есть структура в которой 100 параметров из них половина это другие структуры и т. д.
Сложно абстрактно ответить на такой вопрос, поэтому опишу все моменты, которые важны. Получилась мини лекция )
1. Первое, самое простое, о чем стоит задуматься, когда видим в коде гигантскую структуру — все ли у нас верно с точки зрения семантики, т.е. имеет ли смысл такой сложный тип данных или это оверхэд. Может создать несколько простых типов; может стоит использовать базу данных (в случае с базой данных могут вступить в игру другие детали: как часто мы читаем данные, нужно ли поля отображать в блюпринтах и т.д.). Также я всегда рекомендую при написании кода думать о том, будет ли он понятен другому человеку при прочтении, это помогает.
2.1 Размер структуры влияет на физическую память. Размер структуры в байтах равен количеству байт занимаемых каждым полем. Сколько байтов соответствует каждому типу в Unreal можно посмотреть в документации. Указатели имеют размер 8 байт на 64х-битной машине вне зависимости от типа.
Пример:
Вывод получится следующий:
Eсли у вас в структуре 1000 переменных типа int32
, то размер структуры будет 4 * 1000 байт.
Eсли у вас в структуре 1000 переменных типа double
, то размер структуры будет 8 * 1000 байт.
2.2 Структуры выравниваются в памяти (здесь наглядно с картинками можно прочитать). Ее размер может зависеть от порядка полей структуры.
Пример:
Вывод:
Т.е. поля Data1 и Data2 выравнялись до 8 байт, поэтому получилось 4 * 8 = 32 байта (хотя сумма 4 + 8 + 1 + 8 = 21 байт)
Далее, меняем порядок полей у той же структуры:
Вывод:
Два первых поля занимают 5 байт, они упаковались вместе в 8 байт, поэтому получилось 8 * 3 = 24 байта (хотя сумма все та же 21 байт)
2.2 Теперь смоделируем ситуацию, которую вы описали. В C++ имееются ограничения на размер объекта, который можно создать на стеке. В примере я использую шаблон TFixedAllocator, который позволяет аллоцировать массив фиксированного размера:
Код выше скомпилируется. Все ОК (если интересно, можете посчитать сколько памяти занимает FDataStruct3) А теперь увеличим параметр ArrSize до 500:
constexpr int32 ArrSize = 500;
Код не скомпилируется, компилятор выдаст сообщение об ошибке:
fatal error C1126: automatic allocation exceeds 2G
2.3 При создании объекта динамически в куче (heap) таких ограничений нет. USTRUCT динамически создать не получится, но можно, обернуть ее в UObject и создать динамически такой объект, ошибки компиляции уже не будет в данном случае:
3. Если у вас структура с массивом массивов массивов структур и вы волняете поиск по каким-то ключам, и у вас три вложенных цикла, то тут в игру вступает время поиска (можно почитать в интернете про сложность алгоритмов и т.п.). Производительность может упасть легко.
4. Нужно быть аккуратным с копированием больших структур: не делать лишнего, передавать по ссылке везде, где возможно.
5. Если структура заполнена большим количеством данных в блюпринтах, то это может повлять на процесс сериализации/десериализации, чтения/записи на диск в процессе разработки.
6. Полезные указания по использованию структур из документации
Ну и аналогичный вопрос по таблицам. Насколько большими могут быть хранилища данных такие как таблицы? Что лучше 10 маленьких таблиц или 1 большая? Меня интересует на сколько правильно там хранить информацию к которой нужен доступ постоянно ну если не постоянно то с определенной частотой обращаться к этим данным и на сколько велики могут быть эти хранилища для беспроблемной работы.
Если посмотреть в исходники на класс UDataTable, то можно увидеть, что в сухом остатке UDataTable это UObject, который хранит структуры в ассоциативном массиве:
Т. е. в целом это проецируется на обсуждение первого вопроса. Можете представить, что вы объявляете структуру, в которой одно поле - ассоциативный массив структур другого типа.
Хранить данные в таблицах нормальное решение + удобство в том, что данный контейнер с данными могут использовать разные несвязанные друг с другом классы.
В таблице данные сгрупированы также логически, т.е. строки это объекты структуры одного типа. Поэтому просто создавать еще одну таблицу на основе такой же структуры думаю не стоит.
Подводя итог:
Универсального решения естественно нет. Все зависит от конкретной ситуации и как вы используете структуру. Я предпочитаю начинать с семантической оценки. Так же можете почитать про антипаттерн Blob (это в целом про классы, но смысл примерно тот же)
А какие самые большие структуры вы видели за свою практику? Может у вас есть примеры из практики?
Постоянно встречаются:
1. Конфигурационные структуры (например оружия): параметры цветов, анимаций, связи модификаций, настройки стрельбы, ущерба в различных ситуациях.
2. Деревья прокачки персонажа.
3. В проектах с пользовательской информацией: когда необходимо запросить из базы данные о зарегистрированных пользователях, распарсить, проанализировать, отсортировать всю информацию, от которой может зависеть весь внешний вид игры в принципе (структура данных может быть очень! сложной; для примера можно посмотреть как работают API различных сервисов: google, twitter и сколько данных можно получить разными запросами).
Но к слову сказать, я не могу припомнить ситуацию, когда сложная структура была узким местом - это просто хранилище данных. Скорее это будет неправильная группировка данных и в целом работа с данными из этой структуры: поиск, сортировка и т.д.
Last updated
Was this helpful?