ideas
ideas copied to clipboard
API для ресурсов в С++
API ресурсов
Идея в том, чтобы реализовать в C++ понятие "ресурсов" (или "архива"). API для них будет в условном std::resources
или std::archive
.
"Ресурс" - это файл любого расширения (изображения, звук, текст, видео, 3d-модельки, ..., набор байт), который с использованием нового API можно было бы "вшить" в исполняемый бинарник приложения (и не только туда, но об этом позже), и не загружать его "руками" после старта приложения, откуда-то из внешней директории.
API разбивается на 2 части:
- Указание файлов для "ресурсов" и настроек по их хранению - compile-time.
- Обращение к этим файлам - run-time.
Условный пример кода по частям:
- В неком из
.cpp
-файлов проекта определяется статический объект апишки, который constexpr-ово инициализируется, и куда мы указываем все директории/файлы для зашивания, кодек их сжатия (более мощный уменьшит бинарь, но будет чуть медленнее), и т.д.:
static constinit const auto resources_holder = std::resources
::load_resources({"images/", "models/", "license/MIT.txt"});
- В рантайме можно обращаться к файлам:
const std::span<std::byte> logo = resources_holder.get_resource("images/logo.png");
Техническая реализация (кратко, отбросив мелочи)
Если говорить про большинство Unix-ов: для объектных файлов и бинарей используется формат ELF.
Для хранения ресурсов подходит секция .rodata
. Эту секцию загрузчик во время старта приложения загружает в read-only режиме и держит в RAM.
Значит, в процессе компиляции перед линковкой, объектный файл того .cpp
, где создается объект из 1 пункта, должен в .rodata
содержать массив байт - загруженные ресурсы. Отсюда следует, что динамические и статические библиотеки могут являться носителями ресурсов наравне с бинарями.
Польза
Более быстрый запуск приложений, которые читают всякие файлы при старте. Более cache-friendly по сравнению с файлами, которых загрузили куда попало в кучу. Меньше головной боли для небольших приложений, которые имеют внешние ресурсы.
ML-приложения могут проще обращаться к своим моделькам из RAM.
Особенно неплохо будет для игр, где обычно много ресурсов (кроме тех, где они весят суммарно 100гб и то загружаются, то выгружаются из RAM).
https://github.com/cplusplus/papers/issues/28
Работа ведётся в https://wg21.link/p1040