prevector
’s move assignment and move constructor were not noexcept
, which makes it inefficient to use inside STL containers like std::vector
. That’s the case e.g. for CScriptCheck
. This PR adds noexcept
, and also implements the move assignment & ctor, which makes it quite a bit more efficient to use prevector in an std::vector.
The PR also adds a benchmark which grows an std::vector
by adding prevector
objects to it.
merge-base:
ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark |
---|---|---|---|---|---|---|---|---|---|
6,440.29 | 155,272.42 | 0.2% | 40,713.01 | 20,473.84 | 1.989 | 7,132.01 | 0.2% | 0.44 | PrevectorFillVectorDirectNontrivial |
3,213.19 | 311,217.35 | 0.7% | 35,373.01 | 10,214.07 | 3.463 | 6,945.00 | 0.2% | 0.43 | PrevectorFillVectorDirectTrivial |
34,749.70 | 28,777.23 | 0.1% | 364,396.05 | 110,521.94 | 3.297 | 78,568.37 | 0.1% | 0.43 | PrevectorFillVectorIndirectNontrivial |
32,535.05 | 30,736.09 | 0.4% | 353,823.31 | 103,464.53 | 3.420 | 79,871.80 | 0.2% | 0.40 | PrevectorFillVectorIndirectTrivial |
util: prevector’s move ctor and move assignment is noexcept
:
ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark |
---|---|---|---|---|---|---|---|---|---|
6,603.87 | 151,426.40 | 0.2% | 23,734.01 | 21,009.63 | 1.130 | 2,445.01 | 0.3% | 0.44 | PrevectorFillVectorDirectNontrivial |
1,980.93 | 504,813.15 | 0.1% | 13,784.00 | 6,304.32 | 2.186 | 2,258.00 | 0.3% | 0.44 | PrevectorFillVectorDirectTrivial |
19,110.54 | 52,327.15 | 0.1% | 139,816.41 | 51,987.72 | 2.689 | 28,512.18 | 0.1% | 0.43 | PrevectorFillVectorIndirectNontrivial |
12,334.37 | 81,074.27 | 0.7% | 125,655.12 | 39,253.58 | 3.201 | 27,854.46 | 0.2% | 0.44 | PrevectorFillVectorIndirectTrivial |
util: implement prevector’s move ctor & move assignment
ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark |
---|---|---|---|---|---|---|---|---|---|
5,262.66 | 190,018.01 | 0.2% | 20,157.01 | 16,745.26 | 1.204 | 2,445.01 | 0.3% | 0.44 | PrevectorFillVectorDirectNontrivial |
1,687.07 | 592,744.35 | 0.2% | 12,742.00 | 5,368.02 | 2.374 | 2,258.00 | 0.3% | 0.44 | PrevectorFillVectorDirectTrivial |
17,930.80 | 55,769.95 | 0.1% | 136,237.69 | 47,903.31 | 2.844 | 28,512.02 | 0.2% | 0.42 | PrevectorFillVectorIndirectNontrivial |
11,893.75 | 84,077.78 | 0.2% | 126,182.02 | 37,852.91 | 3.333 | 28,152.01 | 0.1% | 0.44 | PrevectorFillVectorIndirectTrivial |
As can be seen, mostly thanks to just noexcept
the benchmark becomes about 2 times faster because std::vector
can now use move operations instead of having to fall back to copy everything
I had a look at how this change affects the other benchmarks, and they are all pretty much the same, the only noticable difference is CCheckQueueSpeedPrevectorJob
goes from 364.56ns down to 346.21ns.