【问题标题】:Ada records : detect lost bytes, propose optimisationAda 记录:检测丢失的字节,提出优化
【发布时间】:2019-11-16 06:35:30
【问题描述】:

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

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

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

请注意,我还没有(还)在保存任何丢失的 位(这里不需要 pragma pack,也不需要像 @ 中的严格连续记录的 rep. 子句987654322@)。目前只有字节。

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

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. 有一个隐藏的编译选项、编译指示或现有的 GNAT 工具可以提供帮助(例如 pragma component_alignment 或 pragma optimize_alignment,但我不能说他们是否解决了这个问题,因为它会影响 对齐,但不一定对齐+排序)

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

【问题讨论】:

    标签: record ada representation ada2012


    【解决方案1】:

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

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

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

    【讨论】:

    • 好吧,我花了一些时间才认为您的答案是正确的。正如您所说,我在问题中说明了所有选项。但是,是的,没有自动工具可以为我们完成这项工作,所以定制的东西是唯一的选择。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 2014-09-21
    • 1970-01-01
    相关资源
    最近更新 更多