目录

避免高频虚函数调用引起的性能损耗

如何构造一个灵活函数工厂


避免高频虚函数调用引起的性能损耗

提前获取函数地址,防止每次都去查虚函数表(通过模板的类型派生,将虚函数的调用转换为函数指针的调用,这个在实际聚合函数的实现过程之中能够大大提高计算的效率

虚函数是存在虚函数表中的,而如果知道父类和子类的关系,可以提前static_cast 到子类,再直接通过子类去调用,就节省了每次去内存里面寻找虚函数的开销((虚函数的调用需要一次访存指令,一次查表,最终才能定位到需要调用的函数上,这在传统的火山模型的实现上会带来极大的CPU开销。

class IAggregateFunction : public std::enable_shared_from_this<IAggregateFunction>
{
public:
  /** The inner loop that uses the function pointer is better than using the virtual function.
      * The reason is that in the case of virtual functions GCC 5.1.2 generates code,
      *  which, at each iteration of the loop, reloads the function address (the offset value in the virtual function table) from memory to the register.
      * This gives a performance drop on simple queries around 12%.
      * After the appearance of better compilers, the code can be removed.
      */ 
using AddFunc = void (*)(const IAggregateFunction *, AggregateDataPtr, const IColumn **, size_t, Arena *);
    virtual AddFunc getAddressOfAddFunction() const = 0;

}

/// Implement method to obtain an address of 'add' function.
template <typename Derived>
class IAggregateFunctionHelper : public IAggregateFunction
{
private:
    static void addFree(const IAggregateFunction * that, AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena * arena)
    {
        static_cast<const Derived &>(*that).add(place, columns, row_num, arena);
    }

public:
    AddFunc getAddressOfAddFunction() const override { return &addFree; }
}

如何构造一个灵活函数工厂

参考AggregateFunctionFactory类

见src/AggregateFunctions/AggregateFunctionFactory.h

参考链接:

ClickHouse源码笔记1:聚合函数的实现 - 云+社区 - 腾讯云