我正在处理RAM严重受限的旧版Ada项目。
为了节省更多功能的内存,我想分析所有记录定义,以便:
请注意,我尚未(尚未)保存任何丢失的位(此处不需要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;
(对示例中的任何错误表示歉意,希望您能理解这一点)
我该怎么做?
-gnatR2s
并在python中编写一个.rep
解析器对于repl子句的上下文,Ada参考手册和GNAT的细微差别,请阅读this link
答案 0 :(得分:1)
我认为您已经陈述了所有选项:使用您提到的特定于实现的编译指示,手动优化和/或编写自定义优化器来分析表示子句,并使用一些(可调)成本函数对它们进行权衡,该函数可交换空间,访问时间等等。就时间和精力而言,编写自定义优化器无疑是最昂贵的。我不知道其他任何“隐藏”选项(如果它们是隐藏的,则可能是有原因的。)
我将首先制定空间预算(如果可能的话),然后分析每种记录类型具有多少填充字节,以便更好地了解它们的分布方式并估算可能的最大字节数量。可以通过删除 all 填充字节来恢复(请注意,实例数量:一个小型实例被大量实例化可能比大型实例(仅实例化一次)对内存占用量的影响更大)。只有到那时,我才能确定减少填充字节的策略:对所有类型或仅对某些类型使用编译指示,手动优化某些记录,或者得出结论,您确实需要自定义优化器。当然,时间和成本在这里很重要。如果工作必须在明天之前完成,我不建议进行广泛的分析。
为进行分析,我只分析-gnatR2
的输出。据我所知(但您可能要检查一下),libadalang
专注于源代码(可能未声明显式表示子句)。关于ASIS,我认为它可能会起作用,但是我怀疑是否值得这样做。使用某些脚本语言解析-gnatR2
的输出可能会更省时。