Ada 95中的if和elsif优化

Ada 95中的if和elsif优化,ada,Ada,我正在从事一个基于Ada的项目,我对这个项目并不十分熟悉,我刚刚看到一些乍看起来似乎效率低下的东西,但这当然取决于编译器可能做什么 if Ada.Strings.Fixed.Trim (Source => Test_String, Side => Ada.Strings.Both) = String_1 then --Do something here elsif Ada.Strings.Fixed.Trim (Source =>

我正在从事一个基于Ada的项目,我对这个项目并不十分熟悉,我刚刚看到一些乍看起来似乎效率低下的东西,但这当然取决于编译器可能做什么

if Ada.Strings.Fixed.Trim
    (Source => Test_String,
     Side   => Ada.Strings.Both) =
    String_1 then
    --Do something here
elsif Ada.Strings.Fixed.Trim
    (Source => Test_String,
     Side   => Ada.Strings.Both) =
    String_2 then

    --Do something else here
end if;

我觉得调用Trim过程并将结果存储在一个字符串变量中,然后在if语句的每个条件下对不同的字符串进行测试会更有效,特别是当有许多条件需要检查时(更不用说使用二进制搜索可能更好)。当然,我可能错了,所以我的问题是,Ada中是否存在一些我不知道的编译时优化问题,这可能会导致Trim函数只调用一次,并且只在if语句的每个条件下测试结果?

这将取决于编译器,而不是语言。当然,GNAT GPL 2013在
-O2
-O3
两次调用
Trim

你(和我)的直觉似乎是对的:修剪一次并存储结果

Trimmed : constant String :=
  Ada.Strings.Fixed.Trim (Source => Test_String, Side => Ada.Strings.Both);
。。。虽然我个人会写

Trimmed : constant String :=
  Ada.Strings.Fixed.Trim (Test_String, Side => Ada.Strings.Both);

在这种情况下,没有人需要命名参数关联来澄清程序员的意图

虽然我对您的评估或Simon的回答没有任何异议,但值得记住的是,优化实际上意味着什么

如果每次调用“trim”都需要(保守地)0.1ms的CPU时间,而重写需要2分钟,那么节省的盈亏平衡点就是该特定语句的100多万次执行

这当然忽略了(a)积极的一面,即获得经验的价值,以及(b)消极的一面,即CPU时间现在不如你的时间宝贵。(c)我们也花了很多时间讨论优化问题

关于“Ada中的编译时优化”,Ada语言没有对此做任何说明。这里要说的是,程序的行为必须像函数被调用两次一样,也就是说,它必须产生相同的结果。但是,如果编译器“知道”该函数第二次将生成完全相同的结果,那么它可以生成只调用它一次的代码。一般来说,它不能对函数调用执行此操作,因为函数可能包含副作用或使用其值可能已更改的全局变量。在这种情况下,由于
Ada.Strings.Fixed.Trim
的效果是由语言定义的,而且这些效果确实保证了效果是相同的,因此理论上,编译器可以将此函数标记为可以优化具有完全相同参数的调用的函数。(一个
Pure
包中的函数肯定可以消除第二次调用,但不幸的是,
Ada.Strings.Fixed
并没有被Ada语言定义为
Pure
),要想知道编译器是否真的进行了这种特殊的优化,您必须尝试并检查代码。我相信,如果
Test\u String
没有标记为
Volatile
,那么编译器可以假设它的值对于每个
Ada.Strings.Fixed.Trim
调用都是相同的(也就是说,调用之间不能被另一个任务更改),但我不能100%确定这一点


我会声明一个常数来保存结果(比如Simon),但对我来说,这更多的是出于避免重复代码的愿望,而不是出于对效率的考虑。

我认为我们不需要担心这种情况下的效率。但是编码风格确实需要改进。在我看来,定义一个变量来保存修剪函数的结果是一种更好的做法。程序逻辑更加清晰,易于维护


假设您要将Trim函数更改为另一个函数或更改传入的参数,只需更改一个位置。虽然这种情况只有两个地方,但您仍然有可能出错。如果有更多的案例需要测试,那么肯定会有遗漏的案例。

我完全同意,这不是效率问题,而是可读性问题。可悲的事实是,这个项目充满了像这样糟糕的决策,这只是一个简单的例子。我想我的问题中不清楚,但我真的在想“用不同的方式做会更可读。”鉴于这是安全关键代码,我很难理解这样的代码是如何通过独立的代码审查的,因为可读性差会妨碍可维护性。现在,我是一个需要维护它的可怜的草皮。为了可读性、清晰性和可维护性,我完全同意你的观点——但这还不包括在问题中!我喜欢的模式是一个常量字符串,如果需要,可以在declare块中调用Trim-in初始化。Ada的堆栈可变长度存储设施是其中一个“次要”功能,在实践中大大减少了虫子的滋生地。(与malloc/free相比,它也是“高效的”)问题是,您需要多少权限/自由来重构和改进它?这可能要归结为重新鉴定它的成本。是的,尽管我写这个问题是希望获得更多的洞察力,这是有效的!我真的没有任何自由,我只需要添加我被告知要添加的功能,我觉得这会让情况变得更糟。项目中没有时间做其他事情。