我正在处理一个具有重大 RAM 限制的遗留 Ada 项目。
为了节省额外功能的内存,我想分析所有记录定义,以便:
- 检测漏洞(即浪费的字节)
- 提出一个最小化内存占用的记录声明顺序(或表示)(使用一些应该类似于背包问题的算法)
请注意,我(还没有)在保存任何丢失的位的过程中(这里不需要,也不需要 rep. 子句,用于像这个问题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(如何在不编译单元的情况下获得代表条款?)
- 只需
-gnatR2s
在所有编译单元上使用并在 python 中编写.rep
解析器 - 有一个隐藏的编译选项,一个 pragma 或现有的 GNAT 工具可以提供帮助(如pragma component_alignment或pragma optimize_alignment,但我不能说他们是否解决了这个问题,因为它会影响对齐,但不一定是对齐 + 排序)
有关 repl 子句、Ada 参考手册和 GNAT 小差异的上下文,可以阅读此链接