在 C(++) 中优化远离函数表
Posted
技术标签:
【中文标题】在 C(++) 中优化远离函数表【英文标题】:Optimising away function table in C(++) 【发布时间】:2013-06-03 08:57:05 【问题描述】:为了使程序的一部分易于单元测试,我想让它采用一个函数表,该表可以指向操作系统原语(即报告我们可以提供一组剪贴板目标的函数) 或测试版本。理想情况下,虽然我不希望在实时版本中有函数表的开销,但只是它借给代码的额外结构。所以我想用某种方式告诉编译器函数表永远不会改变,这样它就可以优化查找。像这样的东西(用于说明的简单实现):
#ifndef TEST
const
#endif
static struct
void (*reportTargets)(size_t targetc, const char **targetv);
[...]
interfaceToOutside
#ifndef TEST
=
reportTargetsLive,
[...]
#endif
;
这可能会奏效吗?如果没有关于如何实现(或做得更好)的好建议?
【问题讨论】:
这是 C 还是 C++?如果是后者,那么您基本上是在描述虚函数,编译器通常非常擅长优化...... 我认为这不值得打扰,而且我不确定编译器是否会始终优化调用以避免间接调用(这在实践中可能无关紧要)。 Oli,我原以为虚函数的语义实际上阻止了编译器完全优化查找(例如,如果函数是合适的候选者,则内联)。编辑:也就是说,我总是可以#ifdef virtual 关键字。 Basile,我意识到收益通常是微乎其微的,我要求的兴趣与实用价值一样多。 我不会打扰#ifdef
ing 任何事情(除非分析器告诉我)。相反,我会为所需的操作系统功能使用带有虚拟功能的接口,并为您正在开发的操作系统和单元测试提供实现。这使得代码比#ifdef
d 手写的vtables 更简洁,更易于维护。它提供了使用剪贴板服务的代码关注点与该服务的实现的清晰分离。作为奖励,它有助于以后移植到其他操作系统,您可以在其中提供接口的另一种实现。
【参考方案1】:
所以我想用某种方式告诉编译器函数表永远不会改变(...)
好吧,声明所有const
(顺便说一句,你应该在static
和struct
之间交错第一个const
):
#ifndef TEST
# define CONST const
#else
# define CONST
#endif
static CONST struct
void (*CONST reportTargets)(size_t targetc, const char **targetv);
[...]
interfaceToOutside
#ifndef TEST
=
reportTargetsLive,
[...]
#endif
;
#undef CONST
(宏名不好,我知道)。
现在,
这可能会奏效吗(...)?
我想是这样,但您仍应检查生成的汇编代码(gcc
/g++
的-S
选项)。
【讨论】:
【参考方案2】:您可以使用静态内联函数创建 2 个结构,而不是函数指针。一个是测试用的,一个是真实的。现在,根据您实例化模板的方式,您要么处于测试模式,要么处于实时模式。
struct Live
static void Report(const std::string& report) ReportLive(report);
;
struct Test
static void Report(const std::string& report) ReportTest(report);
;
template<typename T>
class Reporter
public:
void doReport()
//some stuff todo
T::Report(report);
//other stuff todo
;
这只是一个想法。内联代码时,编译器将(完全)优化结构。此外,您可以通过实现不同的结构来选择不同的测试行为。
【讨论】:
以上是关于在 C(++) 中优化远离函数表的主要内容,如果未能解决你的问题,请参考以下文章