一段时间以来,我一直在玩弄一种编程语言的想法:它本质上是 C++ 和 Java 的语法,适用于系统编程(或实际上任何需要高性能的编程),但在我看来,比 C++ 更有趣的语法。我正在考虑如何处理分层类结构中的虚拟方法(我的语言不包括多重继承),以及避免 vtable 查找的方法。我的问题是双重的:
- 据我了解,vtable 查找如此影响性能的原因(至少在游戏开发等时间紧迫的场景中)是因为它需要延迟对象 vtable 指针,而这个 vtable 通常是缓存未命中。这是正确的,还是我错过了问题的一部分?
- 我对部分解决方案的想法是:如果编译器可以完全确定对象的类型(即,它不能是从它认为的类型派生的类型),并且该对象作为参数传递给函数,其类型为对象类型的超类,然后函数中调用的虚方法的位置可以作为一种“隐藏”参数传递,该参数在编译时添加。也许一个例子会有所帮助:
考虑以下类层次结构的伪代码:
class Animal {
public void talk() { /* Generic animal noise... */ }
// ...
}
class Dog extends Animal {
public void talk() { /* Override of Animal::talk(). */ }
// ...
}
void main() {
Dog d = new Dog();
doSomethingWithAnimal(d);
}
void doSomethingWithAnimal(Animal a) {
// ...
a.talk();
// ....
}
请记住,这是伪代码,而不是 C++ 或 Java 或类似代码。此外,假设 Animal 参数是通过引用而不是值隐式传递的。因为编译器可以看到它d
肯定是 type Dog
,所以它可以将doSomethingWithAnimal
定义翻译成这样的:
void doSomethingWithAnimal(Animal a, methodptr talk = NULL) {
// ...
if ( talk != NULL ) {
talk(a);
} else {
a.talk();
}
// ...
}
然后main
看起来会被编译器翻译成这样的东西:
void main() {
Dog d = new Dog();
doSomethingWithAnimal(d, Dog::talk);
}
显然,这不会完全消除对 vtable 的需求,并且可能仍需要为无法确定对象确切类型的情况提供 vtable,但是您对此作为性能优化有何看法?我计划尽可能使用寄存器传递参数,即使参数必须溢出到堆栈上,堆栈上的 methodptr 参数更有可能是缓存命中而不是 vtable 值,对吧?任何和所有的想法都非常感谢。