if和elsif优化在Ada 95中

时间:2013-12-20 04:32:46

标签: 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 => Test_String,
     Side   => Ada.Strings.Both) =
    String_2 then

    --Do something else here
end if;

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

4 个答案:

答案 0 :(得分:6)

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

你(和我)的直觉似乎是正确的:做一次修剪并保存结果......

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);

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:3)

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

如果每次调用“trim”(保守地)占用0.1ms的CPU时间,并且重写需要2分钟,那么保存的盈亏平衡点将超过该特定声明的100万次执行!

这当然忽略了(a)积极方面,获得经验的价值,以及(b)从消极方面看,现在CPU时间比你的时间更有价值。 (c)我们讨论优化的时间也是如此!

答案 3 :(得分:3)

关于“Ada中的编译时优化”,Ada语言没有说明这一点。这里所说的只是程序必须表现得好像函数被调用了两次,即它必须产生相同的结果。但是如果编译器“知道”该函数第二次产生完全相同的结果,它就可以生成只调用一次的代码。它通常不能对函数调用执行此操作,因为函数可能包含副作用或使用其值可能已更改的全局变量。在这种情况下,由于Ada.Strings.Fixed.Trim的效果是由语言定义的,并且因为这些效果确实保证了效果相同,所以理论上,编译器可以将此函数标记为使用该函数调用的函数。可以优化完全相同的参数。 (Pure包中的函数肯定是可以消除第二个调用的函数,但遗憾的是,Ada.Strings.Fixed未被Ada语言定义为Pure。)要查找但是,编译器是否实际执行了此特定优化,您必须尝试并检查代码。我相信如果Test_String未标记为Volatile,则允许编译器假设其值对于每个Ada.Strings.Fixed.Trim调用都是相同的(即,它不能被另一个{{1}}调用在电话之间的任务),但我不是100%肯定这一点。

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