Given ~the following with the implementations doing a trivial add and mod:
class Base
{
virtual void Call() = 0;
};
class A : public Base
{
void Call() override;
};
class B : public Base
{
void Call() override;
};
I wanted to compare the performance of various call types:
- virtual
- direct member calls
- std::function
- boost::function
- My hacky implementation of a std function like object
Results (I think I won)::
Debug
g++-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0
`-g -std=gnu++20`
| ns/op | op/s | err% | total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
| 29.23 | 34,216,563.53 | 1.5% | 8.15 | `base->Call()30.49 | 32,793,129.79 | 2.0% | 8.57 | `base->Call()`
| 23.01 | 43,458,913.64 | 1.9% | 6.48 | `a->Call()`
| 21.77 | 45,926,564.46 | 2.3% | 6.22 | `b->Call()`
| 99.60 | 10,040,487.24 | 1.6% | 27.72 | `function &Base::Call, base`
| 90.66 | 11,030,408.01 | 1.8% | 25.21 | `function &A::Call, a`
| 91.46 | 10,934,136.38 | 1.4% | 25.37 | `function &B::Call, b`
| 83.14 | 12,027,721.56 | 1.7% | 23.06 | `boost function &Base::Call, base`
| 22.5275.94 | 44,411,239.4213,168,925.84 | 12.3% | 6.2921.04 | `a->boost function &A::Call()`, a`
| 1972.89 | 50,271,899.8613,718,884.93 | 12.3% | 5.5620.33 | `b->oost function &B::Call()`, b`
| 92.7831.40 | 10,778,025.7331,847,168.31 | 2.17% | 25.84 8.71 | `function &Base::Callpointer direct base, base`&Base::Call `
| 86.2524.96 | 11,593,985.8040,071,270.39 | 1.32.9% | 24.09 7.04 | `function &A::Callon pointer direct a, a`&A::Call`
| 84.7226.24 | 11,803,082.1238,110,580.64 | 1.48% | 23.55 7.36 | `function &B::Callon pointer direct b, b`&B::Call`
| 76.1537.16 | 13,131,281.2326,907,735.45 | 1.32.0% | 21.3010.19 | `boost Sean::function &Base::Calla|b, base`&A|B::Call`
| 69.633.42 | 14,364,610.5629,924,713.87 | 1.38% | 19.48 9.23 | `boost Sean::function &A::Calla, a`&A::Call`
| 69.631.93 | 14,360,809.7231,318,966.50 | 1.42.3% | 19.44 8.83 | `boost Sean::function &B::Callb, b`&B::Call`
| 29.936.97 | 33,412,567.437,078,341.54 | 12.8% | 8.337.52 | `function pointerSean::function direct basea|b, &Base&A|B::Call ``
| 25.071.92 | 39,891,310.545,629,125.73 | 1.92.6% | 6.9813 | `function pointerSean::function direct a, &A::Call`
| 231.73 | 42,142,903.236,022,102.98 | 1.52.9% | 6.6107 | `function pointerSean::function direct b, &B::Call`
| 33.8824 | 29,519,892.8030,086,109.45 | 1.73.0% | 9.3823 | `Sean::function a|b, &A|B::CallParams`
| 30.451.82 | 32,840,113.071,428,888.00 | 1.62.9% | 8.4380 | `Sean::function a, &A::CallParams`
| 31.132.14 | 32,127,053.171,111,968.50 | 1.82.5% | 8.6086 | `Sean::function b, &B::CallParams`
| 26.248.15 | 38,106,875.485,519,154.34 | 1.73.2% | 7.3186 | `Sean::function direct a|b, &A|B::CallParams`
| 21.212.08 | 47,157,137.215,284,728.74 | 2.13.7% | 5.916.16 | `Sean::function direct a, &A::CallParams`
| 21.2874 | 46,993,349.255,999,870.49 | 2.03.3% | 5.926.10 | `Sean::function direct b, &B::CallParams`
| 33.2097 | 30,123,997.429,440,925.19 | 1.82.9% | 9.2844 | `Stemplate sean::function direct a|b, &A|B::CallParams`
| 29.7431.43 | 33,629,366.151,813,589.58 | 2.02% | 8.2370 | `Stemplate sean::function direct aa, &A::CallParams`
| 30.871.62 | 32,392,540.641,620,852.76 | 2.03% | 8.6276 | `Stemplate sean::function direct bb, &B::CallParams`
| 27.3633.81 | 36,549,522.1629,576,909.20 | 12.4% | 7.669.39 | `Sean::function directtemplate check sean::function a|b, &A|B::CallParams`
| 20.5230.79 | 48,722,650.8232,481,714.89 | 2.19% | 5.78.54 | `Sean::function direct atemplate check sean::function a, &A::CallParams`
| 20.849.19 | 47,990,124.5834,256,903.56 | 1.83.1% | 5.818.16 | `Sean::function direct btemplate check sean::function b, &B::CallParams`