我正在C++项目中使用用 C 编写的高性能/并行图形库。它提供了一个结构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, ...)
。
但是,性能在这里是一个关键方面。与使用此类适配器类相关的性能损失是什么?与使用"裸"库相比,我是否应该预期性能下降?
如果你的insertEgde只是将调用转发到stinger_insert_edge_pair那么对stinger_insert_edge_pair的普通调用和g->insertEdge之间生成的代码(很可能)没有区别(前提是你删除了虚拟说明符)。比较通过普通调用和适配器调用生成的汇编代码将公平地输入适配器引入的开销。
插入边缘必须是虚拟的吗?你打算有图的子类吗?但同样,与函数执行本身的实际成本相比,虚拟函数调用的成本几乎可以忽略不计。
如果使用简单的inline
方法,编译器应在调用时内联它们,因此不会有任何性能损失。但请注意,您不应为此使用虚函数。
虚拟函数通常无法内联,因此函数调用的开销相同(在堆栈上推送参数、管道和缓存的可能中断等)。在实践中,例行函数调用非常快 - 按照时钟周期的顺序。确定这是否合适的唯一方法是在您自己的应用程序上进行测试。