Я работаю над устаревшим проектом Ada со значительными ограничениями ОЗУ.
Чтобы сэкономить память для дополнительных функций, я хотел бы проанализировать все определения записей, чтобы:
- обнаружить дыры (т. Е. Потрачено впустую байт )
- предлагает порядок объявления записей (или представление), который минимизирует объем памяти (с некоторым алгоритмом, который должен быть похож на проблема ранца )
Обратите внимание, что я (пока) не в процессе сохранения любых потерянных битов (здесь не требуется pragma pack
, ни пункта отчета для строго смежных записей, как в этот вопрос ). Пока только байты.
Упрощенный пример (реальные записи более сложны и могут иметь дискриминанты, помеченные типы):
type My_Record is record
field1 : Foo; -- enum with 3 values
field2 : Bar; -- some other record
field3 : Float; -- 32 bits
field4 : Flex;-- enum with 12 values
end record;
Его -gnatR2s
вывод будет выглядеть (32-битный мир):
for My_Record'Alignment use 4;
for My_Record use record
field1 at 0 use 0.. 7;
field2 at 4 use 0..47; -- 3 bytes lost from field 1
field3 at 12 use 0..31; -- 2 bytes lost from field 2
field4 at 16 use 0.. 7; -- another 3 bytes lost
end record;
Что я хотел бы сделать (запись, оптимизированная для использования памяти):
-- rewrite record, not the preferred way since record writing order may have some human readable context purpose
type My_Record is record
field2 : Bar; -- 2 unused bytes
field1 : Foo; -- 1 byte left
field4 : Flex; -- 0 byte left
field3 : Float; -- 4 bytes used
-- 0 wasted bytes
end record;
или
-- preferred way : keep record declaration, but force rep. clause
type My_Record is record
field1 : Foo;
field2 : Bar;
field3 : Float;
field4 : Flex;
end record;
-- optimization is here
for My_Record'alignment use 4;
for My_Record use record
field2 at 0 use 0..47;
field1 at 6 use 0.. 7; -- exploit the Bar unused bytes
field4 at 7 use 0.. 7; -- exploit the Bar unused bytes
field3 at 8 use 0..31;
end record;
(извиняюсь за любую ошибку в примере, надеюсь, вы поняли)
Как я могу это сделать?
- ASIS (но у меня 0% навыка, я даже не уверен, что он может делать то, что я хочу)
- libadalang (как он получает выражения rep. Без компиляции модулей?)
- просто используйте
-gnatR2s
на всех модулях компиляции и напишите .rep
парсер в python
- есть скрытая опция компиляции, прагма или существующий инструмент GNAT, который может помочь (например, pragma component_alignment или pragma optimize_alignment , но я не могу сказать, если они решить вопрос, так как он влияет на выравнивание , но не обязательно выравнивание + упорядочение )
Для контекста в пунктах repl, Справочном руководстве Ada и небольших различиях GNAT можно прочитать эту ссылку