Details
-
Task
-
Resolution: Unresolved
-
Minor
-
master
-
0
Description
std::function owns a copy of the functor, hence when it is copied the functor also has to be copied, potentially by heap allocation. A FunctionRef (future std::function_ref) simply keeps a non-owning pointer to the functor.
I benchmarked my implementation of FunctionRef against folly's and std::function, with a varying number of pointers in the functor state (emulating the number of reference captures in a lambda):
BM_PassLambda<FunctionRef, 1> 2.30 ns 2.29 ns 307459855
|
BM_PassLambda<FollyFunctionRef, 1> 2.31 ns 2.29 ns 305012222
|
BM_PassLambda<FollyFunction, 1> 2.40 ns 2.38 ns 295118321
|
BM_PassLambda<StdFunction, 1> 2.29 ns 2.27 ns 308680084
|
BM_PassLambda<FunctionRef, 2> 2.30 ns 2.29 ns 303715306
|
BM_PassLambda<FollyFunctionRef, 2> 2.29 ns 2.28 ns 307226404
|
BM_PassLambda<FollyFunction, 2> 2.38 ns 2.37 ns 294667363
|
BM_PassLambda<StdFunction, 2> 2.27 ns 2.26 ns 310410274
|
BM_PassLambda<FunctionRef, 3> 2.30 ns 2.30 ns 305390136
|
BM_PassLambda<FollyFunctionRef, 3> 2.30 ns 2.29 ns 304009450
|
BM_PassLambda<FollyFunction, 3> 2.37 ns 2.36 ns 297519116
|
BM_PassLambda<StdFunction, 3> 19.1 ns 19.0 ns 36579503
|
BM_PassLambda<FunctionRef, 4> 2.29 ns 2.28 ns 307026970
|
BM_PassLambda<FollyFunctionRef, 4> 2.29 ns 2.28 ns 307335663
|
BM_PassLambda<FollyFunction, 4> 2.37 ns 2.36 ns 295700515
|
BM_PassLambda<StdFunction, 4> 19.6 ns 19.5 ns 35708091
|
BM_PassLambda<FunctionRef, 8> 2.28 ns 2.28 ns 306343052
|
BM_PassLambda<FollyFunctionRef, 8> 2.29 ns 2.29 ns 306447659
|
BM_PassLambda<FollyFunction, 8> 19.2 ns 19.1 ns 36505296
|
BM_PassLambda<StdFunction, 8> 19.0 ns 18.9 ns 36901925
|
std::function heap allocates with just 3 pointers.
Example usage:
void Collection::forEach(folly::FunctionRef<void(const Item&)> func) const {
|
for (const Item& item : items) {
|
func(item);
|
}
|
}
|