Ада записи: обнаружить потерянные байты, предложить оптимизацию - PullRequest
1 голос
/ 05 июля 2019

Я работаю над устаревшим проектом Ada со значительными ограничениями ОЗУ.

Чтобы сэкономить память для дополнительных функций, я хотел бы проанализировать все определения записей, чтобы:

  1. обнаружить дыры (т. Е. Потрачено впустую байт )
  2. предлагает порядок объявления записей (или представление), который минимизирует объем памяти (с некоторым алгоритмом, который должен быть похож на проблема ранца )

Обратите внимание, что я (пока) не в процессе сохранения любых потерянных битов (здесь не требуется 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;

(извиняюсь за любую ошибку в примере, надеюсь, вы поняли)


Как я могу это сделать?

  1. ASIS (но у меня 0% навыка, я даже не уверен, что он может делать то, что я хочу)
  2. libadalang (как он получает выражения rep. Без компиляции модулей?)
  3. просто используйте -gnatR2s на всех модулях компиляции и напишите .rep парсер в python
  4. есть скрытая опция компиляции, прагма или существующий инструмент GNAT, который может помочь (например, pragma component_alignment или pragma optimize_alignment , но я не могу сказать, если они решить вопрос, так как он влияет на выравнивание , но не обязательно выравнивание + упорядочение )

Для контекста в пунктах repl, Справочном руководстве Ada и небольших различиях GNAT можно прочитать эту ссылку

1 Ответ

1 голос
/ 06 июля 2019

Я думаю, что вы уже указали все параметры: используя указанную вами реализацию конкретной прагмы, оптимизируйте вручную и / или напишите собственный оптимизатор, который анализирует предложения и оптимизирует их, используя некоторую (настраиваемую) функцию стоимости, которая меняет пространство, время доступаи т. д. Написание собственного оптимизатора, безусловно, будет наиболее затратным с точки зрения времени и усилий.Я не знаю никаких других «скрытых» опций (если они скрыты, то это может быть по причине).

Я бы начал с формулировки космического бюджета (если это возможно), затем проанализировал бы, какбольшое количество байтов заполнения каждого типа записи, чтобы лучше понять, как они распределяются, и оценить потенциальное максимальное количество байтов, которое можно восстановить, удалив все байтов заполнения (обратите внимание, что количество экземпляров: aсоздание экземпляра для мелкого типа может иметь большее влияние на объем памяти, чем большой тип, который создается только один раз).И только тогда я бы определил стратегию сокращения байтов заполнения: использовать прагму для всех типов или только для некоторых типов, оптимизировать некоторые записи вручную или сделать вывод, что вам действительно нужен собственный оптимизатор.Конечно, время + стоимость здесь имеют значение.Я бы не стал рекомендовать подробный анализ, если работа должна быть завершена к завтрашнему дню.

Для анализа я бы просто проанализировал вывод -gnatR2.Из того, что я знаю (но вы, возможно, захотите проверить это), libadalang фокусируется на исходном коде (который может не содержать явного предложения представления).Что касается ASIS, я думаю, что это может сработать, но я сомневаюсь, стоит ли это усилий.Анализ вывода -gnatR2 с использованием некоторого языка сценариев, вероятно, будет более эффективным по времени.

...