2

我正在处理一个具有重大 RAM 限制的遗留 Ada 项目。

为了节省额外功能的内存,我想分析所有记录定义,以便:

  1. 检测漏洞(即浪费的字节
  2. 提出一个最小化内存占用的记录声明顺序(或表示)(使用一些应该类似于背包问题的算法)

请注意,我(还没有)在保存任何丢失的的过程中(这里不需要,也不需要 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;

(为示例中的任何错误道歉,我希望你明白这一点)


我怎样才能做到这一点 ?

  1. ASIS(但我的技能为 0%,我什至不确定它是否能做我想做的事)
  2. libadalang(如何在不编译单元的情况下获得代表条款?)
  3. 只需-gnatR2s在所有编译单元上使用并在 python 中编写.rep解析器
  4. 有一个隐藏的编译选项,一个 pragma 或现有的 GNAT 工具可以提供帮助(如pragma component_alignmentpragma optimize_alignment,但我不能说他们是否解决了这个问题,因为它会影响对齐,但不一定是对齐 + 排序)

有关 repl 子句、Ada 参考手册和 GNAT 小差异的上下文,可以阅读此链接

4

1 回答 1

3

我认为您已经说明了所有选项:使用您提到的实现特定的编译指示,手动优化和/或编写自定义优化器来分析表示子句并使用一些(可调)成本函数来交换空间、访问时间等来优化它们。 . 就时间和精力而言,编写自定义优化器肯定是最昂贵的。我不知道任何其他“隐藏”选项(如果它们被隐藏,那么可能是有原因的)。

我将首先制定空间预算(如果可能的话),然后分析每种记录类型有多少填充字节,以便更好地了解它们的分布方式并估计可以通过以下方式恢复的潜在最大字节数删除所有填充字节(注意实例计数:一个小类型被实例化很多可能比只实例化一次的大类型对内存占用的影响更大)。只有这样,我才会确定减少填充字节的策略:对所有类型或仅对某些类型使用 pragma,手动优化某些记录或得出结论,您确实需要自定义优化器。当然,时间+成本在这里很重要。如果这项工作必须在明天之前完成,我不建议进行广泛的分析。

对于分析,我只会解析-gnatR2. 据我所知(但您可能想检查一下),libadalang重点关注源代码(可能未声明明确的表示子句)。关于 ASIS,我认为它可能会起作用,但我怀疑它是否值得付出努力。解析-gnatR2使用某些脚本语言的输出可能会更省时。

于 2019-07-05T22:47:46.053 回答