C/C++:使用适配器模式是否会降低性能
C/C++: Is there a performance penalty for using the adapter pattern?
我正在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
方法,编译器应在调用时内联它们,因此不会有任何性能损失。但请注意,您不应为此使用虚函数。
虚拟函数通常无法内联,因此函数调用的开销相同(在堆栈上推送参数、管道和缓存的可能中断等)。在实践中,例行函数调用非常快 - 按照时钟周期的顺序。确定这是否合适的唯一方法是在您自己的应用程序上进行测试。
相关文章:
- 是否总是可以将使用递归编写的程序重写为不使用递归的程序C++,性能观点是什么?
- 不同版本的编译器(例如GCC)是否会产生不同的性能?
- 在现代C++中,侵入式容器是否仍然比非侵入式容器具有性能优势?
- 与纯 V8 相比,NodeJS 是否有任何性能缺陷或显著开销?
- 通过默认复制构造函数比较 C++ 字符串是否会影响性能,原因为何?
- 隐式转换函数的返回对象时是否会影响性能?
- 为数组赋值时是否存在性能差异
- 在类中始终使用此指针是否有任何性能成本
- 在渲染之前直接上传是否会对性能产生负面影响
- 我是否错过了什么,或者虚拟呼叫的性能并不像人们所说的那样糟糕
- 使用 OpenGL 窗口(如 GLFW)或周围的窗口(如 GTK 或 SDL)是否存在性能差异?
- 在将其尺寸较大的向量移动到容量较小的向量之前,是否可以通过使用Reserve()来提高代码性能
- QSqlQuery 绑定值与 BindValues 与 QString.arg() 是否存在性能差异
- 检查从查询返回的任何行是否包含在字符串中的最高性能方法?
- 在C++代码中使用纯 C 库是否有性能下降/损失
- 使用 const CString& 而不是单独使用 CString 作为函数参数是否有任何性能优势?
- 在 C/C++ 中在特定地址边界上对齐内存是否仍能提高 x86 性能?
- 是否有更好的方法(性能提高 /内置功能)获得矩形的旋转角度
- 在较大的架构上使用UINT8_T时,是否存在性能问题
- 对小型任务多次使用std::async是否性能友好