【发布时间】:2021-12-27 14:04:42
【问题描述】:
根据这个说法:
Trace.Debug("My String" & Integer'Image(x) & "is evaluated" & "or not" & "if my logger is disabled ?" & Boolean'Image(YesOrNo) );
还有Trace.Debug的这个实现:
procedure Debug (Message : in String) is
begin
if Logger.Enabled then -- This boolean is defined during runtime by reading a value in a file
Put_Line(Message);
else
null; -- Do nothing
end if;
end Debug;
我有一个可以管理多个级别日志的软件,我想知道Logger.Enabled等于False时的行为。
我有很多日志调用,有时需要评估复杂的字符串,而且我在实时系统上,所以我不想浪费时间来评估不会打印的字符串。
我想知道编译器是否优化代码以便在Logger.enabled 是False 时不评估Trace.Debug 的参数中的字符串,知道这个布尔值是在运行时通过读取一个值来设置的在一个文件中。
我正在使用 gnat 7.3.2。
【问题讨论】:
-
如果它可以在任何地方内联,它甚至可能会跳过构造 arg;你可以检查asm。如果它不能内联,那么它肯定不会跳过,因为优化器不会知道 Debug() 函数将如何处理您传递的参数。我不认识 Ada,但至少在无日志记录的情况下,您需要此函数是 inlineable 的。也许通过链接时优化,例如
-flto,如果它使用 gcc 样式选项。对于启用日志的情况,编译器仍然可以选择不内联它,但实际上我猜它只会内联对 Put_Line 的调用,因为这就是发生的一切。 -
任何优化都必须与不优化具有相同的结果。由于对表达式求值可能会产生副作用,因此优化通常不可能移除对表达式的求值。
-
问题标题具有误导性。可能使用 arg 的运行时分支不是“空体”。我假设您的 Logger.Enabled 是编译时常量,因为
if(false)算作空函数体,但if(variable) print()肯定不是。正如 cmets 在 flyx 的回答中所讨论的,即使在内联之后,编译器仍然必须发出条件分支,尽管如果编译器足够聪明,连接字符串的工作可能会优化到条件块中。
标签: compiler-optimization ada branch-prediction