Ada记录:检测丢失的字节,建议优化

时间:2019-07-05 16:00:06

标签: record ada representation ada2012

我正在处理RAM严重受限的旧版Ada项目。

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

  1. 检测漏洞(即浪费了个字节
  2. 提出一条记录声明顺序(或表示形式),以最大程度地减少内存占用(使用某些应类似于Knapsack problem的算法)

请注意,我尚未(尚未)保存任何丢失的(此处不需要pragma pack,也不需要用于严格连续记录的rep。子句在this question中)。现在只有字节。

简化的示例(现实世界中的记录要复杂得多,可能会有判别式,标记类型):

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并在python中编写一个.rep解析器
  4. 有一个隐藏的编译选项,实用程序或现有的GNAT工具可能会有所帮助(例如pragma component_alignmentpragma optimize_alignment,但我不能说他们是否解决了此问题,因为它影响 alignment ,但不一定 alignment + ordering

对于repl子句的上下文,Ada参考手册和GNAT的细微差别,请阅读this link

1 个答案:

答案 0 :(得分:1)

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

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

为进行分析,我只分析-gnatR2的输出。据我所知(但您可能要检查一下),libadalang专注于源代码(可能未声明显式表示子句)。关于ASIS,我认为它可能会起作用,但是我怀疑是否值得这样做。使用某些脚本语言解析-gnatR2的输出可能会更省时。