Monday, June 24, 2013

Making C++ time measurement simple


Time flies like an arrow

-- Common example showing ambiguities in natural languages (how many interpretations does it have?)

There is only one reason why I'm writing this blog entry: I simply think it's annoying to see well designed C++ code interspersed with POSIX or Windows/Mac specific functions used for timing various parts of the code. A much better alternative is to use the chrono library from either boost or C++11. So to prove to myself and to others that it is simple to use the chrono library I'll put together a simple, here I really mean dead simple, old fashioned stopwatch driven by the chrono library.
Since I'm using C++11 I can either use the C++11 chrono library or the boost version of the library. Here I'll use the boost version for the simple reason that it has a larger selection of clocks for driving my stopwatch.
Why a stopwatch? Well, a stopwatch needs to get hold of the current time, it will have to calculate the difference between two points in time, it should be able to give back results in various units of time and it should preferably be able to return time measurements in a type chosen by the user. Additionally it would be good if it also could be configured to use different types of clocks for measuring time. All in all a stopwatch will show the ease or difficulty in using the chrono library.
At a first glance the chrono library looks a little too complicated for something that should be relatively intuitive. However, a few minutes down in the documentation, it's clear that the chrono facility is based on three basic concepts making it very simple to build devices measuring time:
·         clock
·         timepoint
·         duration
The concepts mean exactly what the intuitive meaning of their respective name is. A timepoint is, well, a point in time. A duration is exactly what the name implies - a time span. Having two timepoints I can create a duration by subtracting them. Finally, a  clock gives me access to the current time. There is a little more to it than that but it's enough to get started building things that measure time.
Because modern C++ is what it is, the timepoint and duration are obviously templates. This is most probably a good thing since hopefully many computations will be done at compile time which may be important when measuring time. For right now I'll mostly ignore the template aspect of the chrono library since it distracts from the main ideas. The implementation at the end of this blog entry shows how the template parameters fit into the picture.
With the three concepts – timepoint, duration and clock - together with the ratio facility I should be able to pound out a simple old fashioned stopwatch class in a few lines of code. The ratio facility is needed since duration represents a time span as a count and a period where the period is expressed using a ratio which in turn represents the number of seconds in each period. For example, std::ratio<3600*24*7> corresponds to one week and std::ratio<1,1000> corresponds to a millisecond.
The design is simple. The stopwatch has two buttons – a button that starts and stops the watch when clicked and one button that resets the clock. By having a single button for starting and stopping I don't have to torture my brain with what to do when, say a start button is pushed twice in a row. Just as with an old fashioned stopwatch I can reset the watch both when it's ticking and when it is stopped. If resetting the watch while it's ticking the watch will move back to time zero and continue ticking.
The interface, ignoring constructors and destructors, would then look something like:
// R – return type for getting measured time
class StopWatch{
 
  // start/stop and reset
  void click();
  void reset();

  // get elapsed time
  R getElapsedTimeNs()const;
  R getElapsedTimeUs()const;
  R getElapsedTimeMs()const;
  R getElapsedTimeSec()const;
  R getElapsedTimeMin()const;
  R getElapsedTimeHours()const;
  R getElapsedTimeDays()const;
  R getElapsedTimeWeeks()const;

  // get state
  bool isRunning()const noexcept;
  bool isStopped()const noexcept;
 
};
So far, nothing from the chrono library has been introduced. The interface, with the exception of the template parameter, looks the way I could have designed a stopwatch based on any time library. This is a good thing since if things work out OK the chrono library does not interfere too much with how time measurement devices are put together.
Now, since the start/stop button and the reset button must change the internal state of the stopwatch a simple way of implementing most of the functionality is to code the click() and reset() functions as a small finite state machine. Since the watch is either ticking or stopped only two states are needed. OK, maybe it's overkill to use a state machine, but it makes for a clean design.
Calculating the current time is done outside the state machine to avoid const issue (the methods reading the current time are const whereas the click and reset methods are non-const).
In order to make it simple to use the stopwatch I've typedefed a few, what I believe, should be commonly used stopwatches:
using SystemStopWatch=StopWatch<std::chrono::system_clock,double>;
using HRStopWatch =StopWatch<std::chrono:: high_resolution_clock,double>;
using SteadyStopWatch=StopWatch<std::chrono::steady_clock,double>;
The system_clock is a clock that represents system time. This means that there is no guarantee that a timepoint returned from the clock will not be ahead of a timepoint retrieved at some later time. After all, someone could have changed the system time. The high_resolution_clock is a clock that has the highest precision of any clock on the machine. Finally, the steady_clock is a clock where that never returns a lower timepoint than a previously returned one plus, it ticks following the real time
A few more stopwatches are needed when measuring process cpu timings:
using ProcRealCpuStopWatch=StopWatch<boost::chrono::process_real_cpu_clock,double>;
using ProcUserCpuStopWatch=StopWatch<boost::chrono::process_user_cpu_clock,double>;
using ProcSystemCpuStopWatch=StopWatch<boost::chrono::process_system_cpu_clock,double>;
using ProcCpuStopWatch=StopWatch<boost::chrono::process_cpu_clock,double>;

Take a look at the documentation of the boost::chrono library to see the exact definition of the clocks. Or better, look through the implementation which is very clear and shows how the time is measured on POSIX, Windows or MAC systems.
The last clock measures time at the thread level:
using ThreadStopWatch=StopWatch<boost::chrono::thread_clock,double>;

Again, to best understand the difference between the clocks, the boost chrono documentation or implementations are the best sources of information.
Using one of the stopwatches is simple enough:
   
  SteadyStopWatch sw;
  sw.click();
 
  // do something
 
  sw.click();
  cerr<<"duration: "<< sw.getElapsedTimeUs()<<": "<<"us"<<endl;
The full implementation is shown at the end of this blog entry.
The implementation gathers most of the use of the chrono library inside a state machine implementation. It could be debated if the R template parameter should be part of the class or not since it does not serve much purpose except making the stopwatch slightly simpler to use. It could also be argued if the getter functions should not return a duration. Here I've rather arbitrary chosen to keep the interface free from chrono specific types.
Well, the time for judgement has come. Let's see, I can easily and transparently use different types of clocks within my stopwatch. I can, as the implementation below shows, transparently represent elapsed time using time periods of my own choice. Getting hold of the current time is simple. The code also uses specific types for time points and durations – that is, time points and duractions are not simply integer values. Also important, many properties of the stopwatch are evaluated at compile time which is exactly what I want when measuring time. Finally, concepts behind the chrono library are far more intuitive than most platform specific time functions.
Here is the implementation:
#include <boost/chrono.hpp>
#include <boost/ratio.hpp>

#ifdef BOOST_CHRONO_HAS_PROCESS_CLOCKS
#include <boost/chrono/process_cpu_clocks.hpp>
#endif

#ifdef BOOST_CHRONO_HAS_THREAD_CLOCK
#include <boost/chrono/thread_clock.hpp>
#endif

// old fashioned stopwatch
template<typename C,typename R=double>
class StopWatch{
public:
  // ctor, assign, dtor
  StopWatch()=default;
  StopWatch(StopWatch const&)=default;
  StopWatch(StopWatch&&)=default;
  StopWatch&operator=(StopWatch const&)=default;
  StopWatch&operator=(StopWatch&&)=default;
  ~StopWatch()=default;

  // start/top and reset
  void click(){fsm_(Event::click);}
  void reset(){fsm_(Event::reset);}

  // get elapsed time
  R getElapsedTimeNs()const{return getElapsedTime<boost::chrono::duration<R,boost::nano>>();}
  R getElapsedTimeUs()const{return getElapsedTime<boost::chrono::duration<R,boost::micro>>();}
  R getElapsedTimeMs()const{return getElapsedTime<boost::chrono::duration<R,boost::milli>>();}
  R getElapsedTimeSec()const{return getElapsedTime<boost::chrono::duration<R,boost::ratio<1>>>();}
  R getElapsedTimeMin()const{return getElapsedTime<boost::chrono::duration<R,boost::ratio<60>>>();}
  R getElapsedTimeHours()const{return getElapsedTime<boost::chrono::duration<R,boost::ratio<3600>>>();}
  R getElapsedTimeDays()const{return getElapsedTime<boost::chrono::duration<R,boost::ratio<3600*24>>>();}
  R getElapsedTimeWeeks()const{return getElapsedTime<boost::chrono::duration<R,boost::ratio<3600*24*7>>>();}

  // get state
  bool isRunning()const noexcept{return state_==State::running;}
  bool isStopped()const noexcept{return !isRunning();}
private:
  // typedefs and states
  using TP=typename C::time_point;
  using DURATION=typename C::duration;
  enum class Event:int{click=0,reset=1};
  enum class State:int{running=0,stopped=1};

  // state of stop watch
  C clock_;
  TP startTime_=TP();
  DURATION accumDuration_=DURATION::zero();
  State state_=State::stopped;

  // general method to read elapsed time expressed in type R units of duration D
  template<typename D>
  R getElapsedTime()const{
    DURATION currDuration{accumDuration_};
    if(state_==State::running)currDuration+=clock_.now()-startTime_;
    return boost::chrono::duration_cast<D>(currDuration).count();
  }
  // state machine driving clock - returns current duration
  void fsm_(Event evnt){
    if(state_==State::running){
      if(evnt==Event::click){
        accumDuration_+=(clock_.now()-startTime_);
        state_=State::stopped;
      }else{
        accumDuration_=DURATION::zero();
        startTime_=clock_.now();
      }
    }else{
      if(evnt==Event::click){
        state_=State::running;
        startTime_=clock_.now();
      }else{
        accumDuration_=DURATION::zero();
        startTime_=TP();
      }
    }
  }
};
// commonly used stop watches
using SystemStopWatch= StopWatch<boost::chrono::system_clock,double>;
using HRStopWatch=StopWatch<boost::chrono::high_resolution_clock,double>;
using SteadyStopWatch=StopWatch<boost::chrono::steady_clock,double>;

#ifdef BOOST_CHRONO_HAS_PROCESS_CLOCKS
using ProcRealCpuStopWatch=StopWatch<boost::chrono::process_real_cpu_clock,double>;
using ProcUserCpuStopWatch=StopWatch<boost::chrono::process_user_cpu_clock,double>;
using ProcSystemCpuStopWatch=StopWatch<boost::chrono::process_system_cpu_clock,double>;
using ProcCpuStopWatch=StopWatch<boost::chrono::process_cpu_clock,double>;
#endif
#ifdef BOOST_CHRONO_HAS_THREAD_CLOCK
using ThreadStopWatch=StopWatch<boost::chrono::thread_clock,double>;
#endif

Friday, June 7, 2013

Events and Messages


In general, we mean by any concept nothing more than a set of operations; the concept is synonymous with a corresponding set of operations.
-- Percy Bridgman, The Logic of Modern Physics, paper

The conversation started to become a little confusing when the guy at the end of the table mentioned that as soon as I have sent the event and when the guy next to me countered with that the event contains the message I need to process.
It's not uncommon to use a mix of terminologies that makes little or no sense when taking a deeper look at them. Events and messages are two of the prime candidates for confusion and misunderstandings in IT discussions. More than often messages and events are talked about in an interchangeable way with consequences – usually bad ones - reaching all the way from design meetings to the bits and bytes stored on the disk platters.
Let's take a look at a reasonable view of what events and messages could and should mean. But, before looking at it lets lay down the usual ground rule for what to expect when looking at concepts within IT: everything is relative – nothing is absolute!
The idea of what the meaning of the word event is could be pretty simple. An event is simply a happening which has a before and an after but not a during. It sounds kind of abstract but it makes a lot of sense. And by the way, what else could it really mean? So, since the idea makes sense and is simple enough I'll stick to it.
Now, what about the historical event when the Visigoths sacked Rome in 410 AD? Clearly there was a before, an after and a during the sacking of the city. Now one might say that something is definitely wrong here - an event having something happening during the event goes against what I mentioned previously. It's exactly the one property an event should not have.
Intuitively it's obvious that sacking of Rome didn't happen instantaneously. It must have taken some time to plunder and demolish a large city even though the Visigoths were probably pretty good fighters. This is where the idea of a relative notion comes into play. That is, to make sense of a concept the meaning of the concept must be relative to something else. In this case it seems to be sensible to relate the meaning of the word event to time ticks. Or more precisely, to classify something as an event I must relate the event to the length of the time ticks through which I view the world.
If I was a historian I might view the history of the world using a clock ticking a year at a time. Doing so, there is a before a year and an after a year but not a during a year. Now I can surely say that the sacking of Rome in 410AD was an historical event.
The obvious question now is: How should I choose the length of my clock ticks? The best answer I have come up with is to choose it in such a way that it helps me focus on what is important in the problems that I'm trying to solve. After all, at the end that's all that matters.
Now, is a message an event? By the definition above it is not. A message would only make sense in a context where I have time to read the message so I would have to set my clock ticks in such a way that there is a time period during which the message exists. A message is therefore by its very nature not an event. In the same way, an event is neither a message.
Am I not nit-picking and dissecting something obvious here? Event or message, does it really matter what I call something? Sometimes it may not matter much but at other times it turns out to be crucial to use consistent terminology when more than a few people are involved in a project. Myself, I believe that using the right terminology is always preferable.
By the way, the sacking of Rome in 407 AD could be classified in a number of ways. Right of the bat, depending on the purpose and the time ticks I use, I could say it was an event, a process or an entity.