Search code examples
c++api-design

API design for measure time spent in a function


Which of the following API:s would be cleanest if you want a way of measuring the time spent in a particular Callable f, in terms of composability, ease-of-use, and clean callsite.

/** Calls `f` with args and returns a TimedResult carrying
* the return value of `f`, and the real time spent in `f`.
*/
template<class Function, class... T>
auto timedCall(Function&& f, T&&... args)

Or

/** Calls `f` with args and returns its result. Before returning the 
* value, it invokes onCompleted(t), where `t` is the time spent in `f`.
*/
template<class OnCompleted, class Function, class... T>
auto timedCall(OnCompleted&& on_completed, Function&& f, T&&... args)

Or even

/** Calls `f` with args. When the function returns, `on_completed(t, std::move(res))`
* is called, where `t` is the time spent in `f`, and `res` is its return value.
*/
template<class OnCompleted, class Function, class... T>
void timedCall(OnCompleted&& on_completed, Function&& f, T&&... args)

Note: The degenerate case of f(args...) being void is ommited for brevity.

Another note: One could hardcode a printout to stderr before timedCall returns the value, but it is good to have the option do something else with the time measurement. For the last two, which is the correct order of f and on_completed.


Solution

  • I find that option 2, with the addition of passing the result as reference-to-const, is the most useful:

    • It gives you the return value back, so it can be used directly
    • The notification callback can use the result to print something like

      "Processed %zu entries in %.7f seconds\n"

      For for different return types, it is possible to use a function object with multiple overloads for operator()()