我正在创建一个渲染引擎。以及我创建任务管理系统的两种方式。创建我自己的自定义回调,在渲染之前和之后调用,或者实现一个任务管理系统,在这个系统中,我必须从父TaskClass派生一个类,然后将它扔进队列。
老实说,我觉得创建回调更好,因为它允许我创建独立于实际渲染引擎的任务管理子系统。这使我可以更专注于渲染引擎,并在以后担心任务管理。
但我的问题是......“使用回调是否代价高昂?” 这种做法在处理器密集型环境中很常见,例如游戏引擎。
答案 0 :(得分:5)
首先,昂贵是相对的,如果你将这些回调称为10000Hz,是的,一些回调实现可能成本太高。但是,一个简单的基于函数指针的回调实际上几乎没有开销。
但最重要的是:这是一个过早优化的例子,当然,因为它看起来你平均每场只能在平均30 fps的游戏中调用这些回调60次。在大多数游戏中,性能问题会更加重要。从一种方法开始,在遇到性能问题时对其进行分析,如果确实不够,则优化它。无论如何,你可能会在数学或AI函数上放松更多的cpu周期。
最后:在许多游戏中,瓶颈是GPU,而不是CPU;)。
答案 1 :(得分:5)
关于在C中使用函数指针执行回调的成本,对于这个小片段
void func1() { }
void func2()
{
void (*funcptr)() = func1;
func1();
funcptr();
}
gcc -S为func2的主体生成以下汇编程序指令:
movq $func1, -8(%rbp)
movl $0, %eax
call func1
movq -8(%rbp), %rdx
movl $0, %eax
call *%rdx
因此,正如预期的那样,您只需支付指针间接费用,即您不必担心性能。
答案 2 :(得分:2)
回调是一个函数指针。通过一个函数调用函数并不是很昂贵,但肯定会产生一些开销 - 函数至少不会内联。
只有你能负担得起才能证明 - 写一个小的测试程序并对其进行分析。根据您调用该函数的频率,开销将占用更少或更多的处理器时间。没有剖析预测和分析是不值得的。
答案 3 :(得分:0)
当它们不涉及闭包时,回调非常便宜。
涉及闭包的回调要贵一些。
答案 4 :(得分:0)
回调本身并不昂贵,但应注意不要做太多的计算。通常回调发布消息,给出信号量/信号等并停止。
答案 5 :(得分:0)
“使用回调是否代价高昂?”
它可以与调用虚函数的成本一样小。
根据您的环境,它可能更昂贵:例如,如果它是从内核模式到用户模式的回调,那么您可能需要做一些聪明和/或昂贵的事情来实现明显的环转换。
回调的一个问题是锁:如果您的代码是多线程和/或线程安全的,那么如果您在调用回调时拥有任何锁(那么取决于回调中的用户代码,例如尝试获得更多的锁)你可能会陷入僵局。
答案 6 :(得分:0)
如果您正在使用Visual Studio并查看任务管理系统,请查看VS 2010 here中的并发运行时,并行模式库和代理库。
您不需要构建自己的任务系统,也可以构建自己的任务系统。