我在C ++项目中使用C语言编写的a high performance/parallel graph library。它提供了结构stinger
(图形数据结构)和类似
int stinger_insert_edge_pair (struct stinger *G,
int64_t type, int64_t from, int64_t to,
double weight, int64_t timestamp) { .... }
但是,大多数情况下,我不想指定时间戳或权重或类型。默认参数会很好。此外,类似OOP的界面会很好:G->insertEdge(u, v)
而不是insert_edge_pair(G, u, v, ...)
。
所以我想创建一个类似
的适配器类class Graph {
protected:
stinger* stingerG;
public:
/** default parameters ***/
double defaultEdgeWeight = 1.0;
/** methods **/
Graph(stinger* stingerG);
virtual void insertEdge(node u, node v, double weight=defaultEdgeWeight);
};
方法insertEdge(...)
只需使用适当的参数调用stinger_insert_edge_pair(this->stingerG, ...)
即可。
但是,性能是一个至关重要的方面。使用这样的适配器类有什么性能损失?与使用“裸”库相比,我是否应该期望性能下降?
答案 0 :(得分:1)
虚拟函数通常无法内联,因此函数调用的开销相同(推送堆栈上的参数,可能会中断管道和缓存等)。实际上,例程函数调用非常快 - 按时钟周期排序。确定这是否合适的唯一方法是在您自己的应用程序上测试。
答案 1 :(得分:1)
如果你使用普通的inline
方法,编译器应该在调用点内联它们,这样就不会有任何性能损失。但请注意,您不应该使用虚函数。
答案 2 :(得分:1)
如果你的insertEgde只是将调用转发给stinger_insert_edge_pair,那么(很可能)在对stinger_insert_edge_pair和g-> insertEdge的普通调用之间生成的代码没有区别(前提是你删除了虚拟指定符)。 比较通过普通调用和适配器调用生成的汇编代码可以为您的适配器带来的开销提供公平的输入。
insertEdge必须是虚拟的吗?你打算有Graph的子类吗?但同样,与功能执行本身的实际成本相比,虚函数调用的成本几乎可以忽略不计。