diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 new file mode 100644 index 0000000..d1a0662 --- /dev/null +++ b/build/Jamfile.v2 @@ -0,0 +1,25 @@ +# Boost Timer Library Build Jamfile + +# (C) Copyright Beman Dawes 2002, 2006, 2011 + +# Distributed under the Boost Software License, Version 1.0. +# See www.boost.org/LICENSE_1_0.txt + +# See library home page at http://www.boost.org/libs/timer + +project boost/timer + : source-location ../src + : usage-requirements # pass these requirement to dependents (i.e. users) + shared:BOOST_TIMER_DYN_LINK=1 + static:BOOST_TIMER_STATIC_LINK=1 + ; + +SOURCES = auto_timers auto_timers_construction cpu_timer ; + +lib boost_timer + : $(SOURCES).cpp ../../chrono/build//boost_chrono + : shared:BOOST_TIMER_DYN_LINK=1 + static:BOOST_TIMER_STATIC_LINK=1 + ; + +boost-install boost_timer ; diff --git a/doc/cpu_timers.html b/doc/cpu_timers.html new file mode 100644 index 0000000..713d28c --- /dev/null +++ b/doc/cpu_timers.html @@ -0,0 +1,693 @@ + + + + + + + +CPU Timers + + + + + + + + + + +
+ +boost.png (6897 bytes) + Timer Library
+ CPU Timers
+ + + + + +
Timer Home    + CPU timers    + Original timers    +
+ +

Introduction

+ + + + + + +
+ Contents
+ Introduction
+ Using the timers
Using auto_cpu_timer
Using cpu_timer
+ Reference
+  <boost/timer/timer.hpp> + synopsis
+   Typedef nanosecond_type
+  + Non-member functions
+      default_format()
+      format()
+   + Class cpu_timer
+     cpu_timer +constructors, destructor
+     cpu_timer +observers
+     cpu_timer +actions
+   Class auto_cpu_timer
+     auto_cpu_timer constructors
+     auto_cpu_timer destructor
+     auto_cpu_timer actions
+ Timer accuracy
Resolution
Other concerns
Recommendations
+ History
+ Acknowledgements
+
+ +

Knowing how long a program takes to execute is useful in both test and +production environments. It may also be helpful if such timing information is broken down +into wall-clock time, CPU time spent by the user, and CPU time spent by the +operating system servicing user requests.

+ +

Class cpu_timer measures +wall-clock time, user CPU process time, and system CPU process time. Class +auto_cpu_timer is a refinement of +cpu_timer that automatically reports the elapsed times when an +auto_cpu_timer object is destroyed.

+ +

Setup

+ +

Boost.Timer is implemented as a separately compiled library, so you must +install binaries in a location that can be found by your linker. If you followed +the + +Boost Getting Started instructions, that's already been done.

+ +

Using the timers

+ +

Using auto_cpu_timer

+ +

The simplest and most common use is to add the two lines high-lighted below +to a scope you want to time. See +auto_cpu_timer_example.cpp +for the source code.

+
+
#include <boost/timer/timer.hpp>
+#include <cmath>
+
+int main()
+{
+  boost::timer::auto_cpu_timer t;
+
+  for (long i = 0; i < 100000000; ++i)
+    std::sqrt(123.456L); // burn some time
+
+  return 0;
+}
+
+

When the auto_cpu_timer object is created, it starts timing. When +it is destroyed at the end of the scope, its destructor stops the timer and +displays timing information on the default output stream, std::cout.

+

The output of this program, run with a debug build on a circa 2006 desktop processor:

+

    5.713010s wall, 5.709637s user + 0.000000s system = +5.709637s CPU (99.9%)

+

In other words, this program ran in 5.713010 seconds as would be measured by a +clock on the wall, the operating system charged it for 5.709637 seconds of user CPU +time and 0 seconds of system CPU time, the total of these two was 5.709637, and that +represented 99.9 percent of the wall clock time.

+ +

The output stream, number of decimal places reported, and reporting format +can be controlled by auto_cpu_timer constructor arguments. Here is +what the output from the above program would look like for several different +sets of constructor arguments:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstructorResulting Output
t5.713010s wall, 5.709637s user + 0.000000s system = 5.709637s + CPU (99.9%)
t(std::cerr, 2)5.71s wall, 5.70s user + 0.00s system = 5.70s CPU (99.9%)
t(1)5.7s wall, 5.7s user + 0.0s system = 5.7s CPU (99.9%)
t(3, "%w seconds\n")5.713 seconds
t("%t sec CPU, %w sec real") + 5.709637 sec CPU, 5.713010 sec real
+

The processing of the format string is described here.

+

Using cpu_timer

+

The following code creates a checkpoint every 20 seconds of user CPU time:

+
+
using boost::timer::cpu_timer;
+...
+nanosecond_type last_checkpoint_time = 0;
+cpu_timer checkpoint_timer;  // start the timer
+
+while (more_transactions)
+{
+  process_a_transaction();
+  if (checkpoint_timer.elapsed().user - last_checkpoint_time > 20*1000000000LL)
+  {
+    ... create a checkpoint ...
+    last_checkpoint_time = checkpoint_timer.elapsed().user;  
+  }
+}
+
+

Reference

+

Specifications are given in the style of the C++ standard library (C++11, +17.5.1.4 [structure.specifications]). An additional Overview element may +be provided to aid understanding. Overview elements are only informative +- actual semantics are given by the other detailed specification elements.

+

Functions not specified as noexcept will throw +std::bad_alloc exceptions if a memory allocation error occurs. Other +errors are reported by time values of -1. [Note: Modern hardware and +operating systems have robust clock subsystems, so such errors are unusual if +even possible at all. -- end note]

+

The Timer library meets the same data race avoidance requirements +as the C++11 standard library (17.6.5.9 [res.on.data.races]). Shared objects of +Timer library types risk undefined behavior unless the user supplies a locking +mechanism. See C++11, 17.6.4.10 [res.on.objects], Shared objects and the +library.

+

+<boost/timer/timer.hpp> +Synopsis

+ + + + +
+
+
namespace boost
+{
+  namespace timer
+  {
+    class cpu_timer;       // wall-clock, user, and system timer
+    class auto_cpu_timer;  // automatic report() on destruction 
+
+    typedef boost::int_least64_t nanosecond_type;
+
+    struct cpu_times
+    {
+      nanosecond_type wall;
+      nanosecond_type user;
+      nanosecond_type system;
+
+      void clear() { wall = user = system = 0LL; }
+    };
+      
+    const int           default_places = 6;
+
+    const std::string&  default_format();
+
+    std::string format(const cpu_times& times,
+                       short places = default_places,
+                       const std::string& format = default_format()); 
+  } // namespace timer
+} // namespace boost
+
+
+ +

Typedef nanosecond_type

+ +

The typedef nanosecond_type provides an implementation defined type capable +of representing nanoseconds. For POSIX and Windows systems, +nanoseconds_type is boost::int_least64_t.

+ +

The underlying type is not based on the Boost Date-Time or Chrono library to avoid a +dependency on a large library. This design choice may change at some future +date.

+ +

Although nanosecond_type is capable of representing one +nanosecond, the actual resolution of common operating system timers may be +much lower. For wall clock time on desktop systems circa 2010, resolution is +often no better than than one microsecond. For user and system time, typical +resolution is 15 milliseconds on Windows and 10 milliseconds on +POSIX.

+ +

Struct cpu_times

+ +

Struct cpu_times packages three elapsed times:

+ +
    +
  • Wall clock elapsed time, equivalent to the time that would be recorded by + a stopwatch.
  • +
  • User central processing unit (CPU) time used by the process, as charged by + the operating system.
  • +
  • System central processing unit (CPU) time used by the process, as charged + by the operating system.
  • +
+ +

Non-member functions

+ +
const std::string&  default_format();
+
+

Returns: std::string(" %ws wall, %us user + %ss system = %ts + CPU (%p%)\n").

+
+
std::string format(const cpu_times& times,
+                   short places = default_places,
+                   const std::string& format = default_format()); 
+
+ +

Overview: Converts the times argument's values to strings +representing seconds to a given number of decimal places, and +inserts them into a return string under control of the format +string.

+ +

Effects: If places is less than 0,  it is set to default_places. If places is +more than 9, it is set to 9. if the format +argument is empty(), it is set to +default_format.

+ +

Returns: A string that is a copy of format, except that any +instances of the sequences shown below are replaced by the indicated value. +Times are reported in seconds, +shown to places decimal places. Percentage is reported to one +decimal place. [Note: percentage may exceed 100% due to differences in +how operating systems measure various times. --end note]

+ +

Format replacement sequences

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
SequenceReplacement value
%wtimes.wall
%utimes.user
%stimes.system
%ttimes.user + times.system
%pThe percentage of times.wall represented by + times.user + times.system
+
+ +

Class cpu_timer

+ +

cpu_timer objects measure wall-clock elapsed time, process elapsed +time charged to the user, and process elapsed time charged to the system.

+ +

Current time values are +obtained as follows: Current wall-clock time is obtained from the Boost.Chrono +high_resolution_clock. Current user and system time values are obtained +from the appropriate operating system API functions such as times() +on POSIX or +GetProcessTimes() on Windows.

+ +

cpu_timer synopsis

+ + + + + +
+ +
    
+    class cpu_timer
+    {
+    public:
+
+      //  constructor, destructor
+      cpu_timer() noexcept;
+     ~cpu_timer() noexcept {}
+
+      //  compiler generated
+      cpu_timer(const cpu_timer&) = default;
+      cpu_timer& operator=(const cpu_timer&) = default;
+
+      //  observers
+      bool              is_stopped() const noexcept;
+      cpu_times         elapsed() const noexcept;
+      std::string       format(int places = default_places,
+                               const std::string& format = default_format()) const;
+      //  actions
+      void              start() noexcept;
+      const cpu_times&  stop() noexcept;
+      void              resume() noexcept;
+    };
+
+

cpu_timer constructor, destructor

+
cpu_timer() noexcept;
+
+

Effects: Constructs an object of type + cpu_timer. Calls start().

+
+
~cpu_timer() noexcept {}
+
+

Effects: None

+
+

cpu_timer +observers

+
bool is_stopped() const noexcept;
+
+

Returns: true if the most recent call to an + action function was to stop(), + otherwise false.

+
+
cpu_times elapsed() const noexcept;
+
+

Overview: If the timer is running, returns the cumulative elapsed + time. If the timer is stopped, returns the cumulative elapsed time previously + stored by stop().

+ +

Returns: If is_stopped(), the stored time values. + Otherwise, the difference between the + current time values and the stored time + values.

+ +
+
std::string format(int places = default_places,
+                   const std::string& format = default_format()) const;
+
+

Overview: Returns a string for the current elapsed time as formatted + by the format function.

+

Returns: timer::format(elapsed(), places, format).

+
+

cpu_timer +actions

+
void start() noexcept;
+
+ +

Effects: Stores the current time values.

+ +

Postconditions: !is_stopped().

+ +
+
cpu_times stop() noexcept;
+
+ +

Effects: If !is_stopped(), stores the difference between +the current time values and the time values +stored by the most recent call to start() or +resume().

+ +

Postconditions: is_stopped().

+ +

Returns: The stored times.

+ +
+
void resume() noexcept;
+
+

Overview: Restarts the timer, accumulating additional elapsed time.

+

Effects: If is_stopped(), store the +current time values less the previously + stored cumulative elapsed times.  Otherwise, no effect. [Note: + Subtracting the previous elapsed times has the effect of accumulating + additional elapsed time. --end note]

+
+

Class auto_cpu_timer

+ +

Class auto_cpu_timer adds a report() +function to class cpu_timer, and automatically calls report() +on destruction.

+ +

auto_cpu_timer synopsis

+ + + + + +
+ +
    
+    class auto_cpu_timer : public cpu_timer
+    {
+    public:
+      explicit auto_cpu_timer(short places = default_places,
+                              const std::string& format = default_format());
+      explicit auto_cpu_timer(const std::string& format);
+      explicit auto_cpu_timer(std::ostream& os,
+                              short places = default_places,
+                              const std::string& format = default_format());
+      auto_cpu_timer(std::ostream& os, const std::string& format);
+
+     ~auto_cpu_timer() noexcept;
+
+      cpu_timer(const cpu_timer&) = default;
+      cpu_timer& operator=(const cpu_timer&) = default;
+
+      void            report();
+
+    private:
+      std::ostream&   m_os;               // exposition only
+      short           m_places;           // exposition only
+      std::string     m_format;           // exposition only
+    };
+
+

[Note: Constructors without a std::ostream& +argument argument imply +std::cout. An argument default is avoided as it would require including <iostream>, +with its high costs, even when the standard streams are not used. --end note]

+

auto_cpu_timer constructors

+
explicit auto_cpu_timer(short places = default_places,
+                        const std::string& format = default_format());
+
+

Effects: Constructs an object of type + auto_cpu_timer.

+

Postconditions: + As if
+
  m_os == std::cout,
+   m_places == places
,
+  m_format == format

+
+
explicit auto_cpu_timer(const std::string& format);
+
+

Effects: Constructs an object of type + auto_cpu_timer.

+

Postconditions: + As if
+
  m_os == std::cout,
+   m_places == default_places
,
+  m_format == format

+
+
explicit auto_cpu_timer(std::ostream& os,
+                        short places = default_places,
+                        const std::string& format = default_format());
+
+

Effects: Constructs an object of type + auto_cpu_timer.

+

Postconditions: + As if
+
  m_os == os,
+   m_places == places
,
+  m_format == format

+
+
auto_cpu_timer(std::ostream& os, const std::string& format);
+
+

Effects: Constructs an object of type + auto_cpu_timer.

+

Postconditions: + As if
+
  m_os == os,
+   m_places ==
default_places,
+  m_format == format

+
+

auto_cpu_timer destructor

+
~auto_cpu_timer() noexcept;
+
+

Effects: If !is_stopped(), +report(). Otherwise, no effects.

+

[Note: Because the function is noexcept, +implementation requires a try/catch or equivalent to ensure no exception +escapes. --end note]

+
+

auto_cpu_timer actions

+
void report();
+
+

Effects: As if:

+
+
m_os << timer::format(stop(), m_places, m_format);
+resume();
+
+ +

[Note: stop() is called because doing I/O while the + timer is running might produce misleading results. --end note]

+ +
+ +

Timer accuracy

+ +

How accurate are these timers?

+ +

Resolution

+ +

The resolution of a clock, and thus timers built on that clock, + is the minimum period time that can be measured. The program + cpu_timer_info.cpp measures + the resolution of cpu_timer.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
O/SProcessorWall-clockCPU
ResolutionCommentsUser
+ Resolution
System
+ Resolution
Windows 7Intel Core i7 860 @ 2.9 GHz366nsSome variation, usually in multiples of 366ns15600100ns15600100ns
Windows 7Intel Mobile T7200 @ 2.0 GHz2050nsMuch variation. Resolution degrades when processor slows, probably due + to known chipset errata. 15600100ns15600100ns
Windows XPIntel Atom N2800 @ 1.0 GHz1437nsSome variation.15625000ns15625000ns
Mac OS X LionIntel circa 20072100ns
+ 2200ns
Some variation within a range.10000000ns10000000ns
Ubuntu Linux 11.4Intel circa 2005516nsVery little variation, typically less than 5ns 10000000ns10000000ns
+ +

Other concerns

+ +

Wall-clock timings are subject to many outside influences, such as the impact + of other processes.

+ +
+ +

cpu_timer and auto_cpu_timer obtain Wall-clock + timings from Boost.Chrono's high_resolution_clock. On Intel + compatible CPU's running Windows, Linux, and Mac OS X, this is a "steady + clock", but may not be steady on other platforms. + cpu_timer_info.cpp reports + whether or not the high_resolution_clock is steady on a + particular platform.

+ +

Steady clocks are defined by the + C++11 standard as clocks for which values never decrease as physical time + advances and for which values advance at a steady rate relative to real time. + That is, the clock may not be adjusted. Clocks that are steady never run + backwards, even when the operating system's clock is reset backwards such as + during a daylight saving time transition.

+ +
+ +

Timings of debug builds are often several times slower + than release builds, because compiler optimization is turned off and + because libraries often supply very expensive error checks on debug builds.

+ +

Synthetic benchmark code may be optimized way by release builds. It may be + necessary to inspect generated code to verify this isn't happening.

+ +

Recommendations

+ +

Think about what is important to your application. For a + production process, the wall-clock time may be what is most important. For + studying the efficiency of code, total CPU time (user + system) is often a much better measure.

+ +

A useful recommendation is to never trust timings unless they are + (1) at least 100 times longer than the CPU time resolution, (2) run multiple + times, and (3) run on release builds. And results that are too good to be true + need to be further investigate.

+ +

Shared libraries (DLL's) may incur extra time delays, including expensive + disk accesses, the first time a timer or other function is called. If that + would be misleading, static linking should be considered.

+ +

History

+ +

Beman Dawes and Rob Stewart developed version 2 of the library.

+ +

Beman did the initial development. Rob contributed many corrections, comments, and suggestions. In + particular, he suggested the resume() and format() + functions, resulting in improved ease-of-use for several use cases.

+ +

Acknowledgements

+

Comments and suggestions came from Greg Rubino, Dave Abrahams, Vicente + Botet, and John Maddock.

+ +
+

Revised: +04 October 2011

+

© Copyright Beman Dawes, 2006
+© Copyright Beman Dawes and Robert Stewart, 2011

+

Distributed under the Boost Software License, Version 1.0. See www.boost.org/ LICENSE_1_0.txt

+ + + + \ No newline at end of file diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..452cb83 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,87 @@ + + + + + + +Boost Timer Library + + + + + + + + + +
+ +boost.png (6897 bytes) + Timer Library
+ Version 2
+
+ + + + + +
Timer Home    + CPU timers    + Original timers    +
+ +

"How long does my C++ code take to run?"

The Boost Timer library +answers that question - portably, and with as little as one #include and one +additional line of code.

The Boost Timer library has two distinct sets of +components.

    +
  • If you are new to the library, please go directly to the version 2 + CPU timers page.
  • +
  • If you are interested in +the original library, now deprecated, read on below.
  • +
+

+ CPU timers

+

These version 2 components conform to current Boost practice:

+
    +
  • The interfaces and their semantics are the same across all platforms.
  • +
  • The internal implementation uses operating system specific APIs to achieve + higher precision and supply functionality not otherwise available. 
  • +
  • The headers live in a sub-directory, <boost/timer/...>.
  • +
  • The content is in a sub-namespace, boost::timer.
  • +
+

+ Original timers

+

These version 1 components are deprecated. They date from the earliest days +of Boost and do not conform to current Boost practice:

+
    +
  • The interfaces are the same across all platforms, but the semantics differ + according to platform. Wall-clock time is measured on Windows, while CPU time + is measured on POSIX-like systems.
  • +
  • The internal implementation uses only C/C++ standard library functions, so + cannot supply desirable precision and functionality.
  • +
  • The headers live in the main Boost header directory.
  • +
  • The content are in namespace boost.
  • +
+
+

Revised: +04 October 2011

+ +

© Copyright Beman Dawes  2001, 2011

+ +

Distributed under the Boost Software License, Version 1.0. See + +www.boost.org/LICENSE_1_0.txt

+ + + + \ No newline at end of file diff --git a/timer.htm b/doc/original_timer.html similarity index 79% rename from timer.htm rename to doc/original_timer.html index 98770b8..3cab889 100644 --- a/timer.htm +++ b/doc/original_timer.html @@ -5,14 +5,66 @@ -Boost Timer Documentation +Original Timers + -

-boost.png (6897 bytes) - Timer Library

+ + + + + +
+ +boost.png (6897 bytes) + Timer Library
+ Original Timers and Progress Display
+ + + + + +
Timer Home    + CPU timers    + Original timers    +
+ +

+ +
+ + + + +
+

These timers are deprecated. They date from the earliest days +of Boost and do not conform +to current Boost practice.

+
    +
  • The interfaces are the same across all platforms, but the semantics differ + according to platform. Wall-clock time is measured on Windows, while CPU time + is measured on POSIX-like systems.
  • +
  • The internal implementation uses only C/C++ standard library functions, so + cannot supply desirable precision and functionality.
  • +
  • The headers live in the main Boost header directory.
  • +
  • The content are in namespace boost.
  • +
+ Please see the Version 2 + CPU timers for replacements that conform to + current Boost practice.
+
+

The timer library provides two headers and three classes:

@@ -201,12 +253,14 @@ compiler (Microsoft and Borland were tested) and the operating system version (Windows NT, Windows 95, etc.)  Thus the std::clock() function was much more reliable, and so was retained even on this platform with its own timer API.


-

© Copyright Beman Dawes 1999.
-Distributed under the Boost Software License, Version 1.0. See -www.boost.org/LICENSE_1_0.txt

+

Revised: +04 October 2011

-

Revised November 07, 2007 -

+

© Copyright Beman Dawes 1999.

+ +

Distributed under the Boost Software License, Version 1.0. See + +www.boost.org/LICENSE_1_0.txt

diff --git a/example/auto_cpu_timer_example.cpp b/example/auto_cpu_timer_example.cpp new file mode 100644 index 0000000..02213e3 --- /dev/null +++ b/example/auto_cpu_timer_example.cpp @@ -0,0 +1,19 @@ +// auto_cpu_timer_example.cpp ------------------------------------------------------// + +// Copyright Beman Dawes 2006 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +#include +#include + +int main() +{ + boost::timer::auto_cpu_timer t; + + for ( long i = 0; i < 100000000; ++i ) + std::sqrt( 123.456L ); // burn some time + + return 0; +} diff --git a/example/timex.cpp b/example/timex.cpp new file mode 100644 index 0000000..f0597ef --- /dev/null +++ b/example/timex.cpp @@ -0,0 +1,47 @@ +// timex: timed execution program ------------------------------------------// + +// Copyright Beman Dawes 2007 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See http://www.boost.org/libs/timer for documentation. + +#include +#include +#include +#include + +int main( int argc, char * argv[] ) +{ + if ( argc == 1 ) + { + std::cout << "invoke: timex [-v] command [args...]\n" + " command will be executed and timings displayed\n" + " -v option causes command and args to be displayed\n"; + return 1; + } + + std::string s; + + bool verbose = false; + if ( argc > 1 && *argv[1] == '-' && *(argv[1]+1) == 'v' ) + { + verbose = true; + ++argv; + --argc; + } + + for ( int i = 1; i < argc; ++i ) + { + if ( i > 1 ) s += ' '; + s += argv[i]; + } + + if ( verbose ) + { std::cout << "command: \"" << s.c_str() << "\"\n"; } + + boost::timer::auto_cpu_timer t(" %ws elapsed wall-clock time\n"); + + return std::system( s.c_str() ); +} diff --git a/include/boost/timer/config.hpp b/include/boost/timer/config.hpp new file mode 100644 index 0000000..adf223d --- /dev/null +++ b/include/boost/timer/config.hpp @@ -0,0 +1,53 @@ +// boost/timer/config.hpp -----------------------------------------------------------// + +// Copyright Beman Dawes 2003, 2006, 2011 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See http://www.boost.org/libs/timer for documentation. + +#ifndef BOOST_TIMER_CONFIG_HPP +#define BOOST_TIMER_CONFIG_HPP + +#include + +#include + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +// enable dynamic or static linking as requested --------------------------------------// + +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_TIMER_DYN_LINK) +# if defined(BOOST_TIMER_SOURCE) +# define BOOST_TIMER_DECL BOOST_SYMBOL_EXPORT +# else +# define BOOST_TIMER_DECL BOOST_SYMBOL_IMPORT +# endif +#else +# define BOOST_TIMER_DECL +#endif + +// enable automatic library variant selection ----------------------------------------// + +#if !defined(BOOST_TIMER_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_TIMER_NO_LIB) +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_timer +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_TIMER_DYN_LINK) +# define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include +#endif // auto-linking disabled + +#endif // BOOST_TIMER_CONFIG_HPP + diff --git a/include/boost/timer/timer.hpp b/include/boost/timer/timer.hpp new file mode 100644 index 0000000..fe78922 --- /dev/null +++ b/include/boost/timer/timer.hpp @@ -0,0 +1,130 @@ +// boost/timer/timer.hpp -------------------------------------------------------------// + +// Copyright Beman Dawes 1994-2007, 2011 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_TIMER_TIMER_HPP +#define BOOST_TIMER_TIMER_HPP + +#include + +#include +#include +#include +#include +#include +#include + +#include // must be the last #include + +# if defined(_MSC_VER) +# pragma warning(push) // Save warning settings +# pragma warning(disable : 4251) // disable warning: class 'std::basic_string<_Elem,_Traits,_Ax>' +# endif // needs to have dll-interface... + +//--------------------------------------------------------------------------------------// + +// TODO: +// +// * Add BOOST_NOEXCEPT where applicable + +//--------------------------------------------------------------------------------------// + +namespace boost +{ +namespace timer +{ + class cpu_timer; + class auto_cpu_timer; + + typedef boost::int_least64_t nanosecond_type; + + struct cpu_times + { + nanosecond_type wall; + nanosecond_type user; + nanosecond_type system; + + void clear() { wall = user = system = 0LL; } + }; + + const short default_places = 6; + + BOOST_TIMER_DECL + const std::string& default_format(); + + BOOST_TIMER_DECL + std::string format(const cpu_times& times, + short places = default_places, + const std::string& fmt = default_format()); + +// cpu_timer ---------------------------------------------------------------------// + + class BOOST_TIMER_DECL cpu_timer + { + public: + + // constructors, destructor + cpu_timer() { start(); } + ~cpu_timer() {} + + // observers + bool is_stopped() const { return m_is_stopped; } + cpu_times elapsed() const; // does not stop() + std::string format(int places = default_places, + const std::string& format = default_format()) const + { return timer::format(elapsed(), places, format); } + // actions + void start(); + const cpu_times& stop(); + void resume(); + + private: + cpu_times m_times; + bool m_is_stopped; + }; + +// auto_cpu_timer --------------------------------------------------------------------// + + class BOOST_TIMER_DECL auto_cpu_timer : public cpu_timer + { + public: + + // Explicit defaults to std::cout are not supplied since such defaults would + // require including , with its high costs, even when the standard + // streams are not actually used. + + explicit auto_cpu_timer(short places = default_places, + const std::string& format = default_format()); + explicit auto_cpu_timer(const std::string& format); + explicit auto_cpu_timer(std::ostream& os, + short places = default_places, + const std::string& format = default_format()) + : m_places(places), m_os(os), m_format(format) + { start(); } + auto_cpu_timer(std::ostream& os, const std::string& format) + : m_places(default_places), m_os(os), m_format(format) + { start(); } + + ~auto_cpu_timer(); + + void report(); + + private: + int m_places; + std::ostream& m_os; + std::string m_format; + }; + +} // namespace timer +} // namespace boost + +# if defined(_MSC_VER) +# pragma warning(pop) // restore warning settings. +# endif + +#include // pops abi_prefix.hpp pragmas + +#endif // BOOST_TIMER_TIMER_HPP diff --git a/index.html b/index.html index 911b5df..d95bd34 100644 --- a/index.html +++ b/index.html @@ -1,47 +1,14 @@ - - - - -Boost Timer Library + - - - - - - - - - - - - -
boost.png (6897 bytes)Home Libraries People FAQ More
- -

Timer library

- -

The timer library supplies a timer class for measuring elapsed time, a -progress_timer class for reporting elapsed time, and a progress_display class -for displaying an indication of progress toward a goal. - -

- -

 

+ +Automatic redirection failed, please go to doc/index.html.
-

© Copyright Beman Dawes, 2001
-Distributed under the Boost Software License, Version 1.0. See -www.boost.org/LICENSE_1_0.txt

- -

07 November, 2007 -

- +

© Copyright Beman Dawes, 2003, 2011

+

Distributed under the Boost Software +License, Version 1.0.

+

See +www.boost.org/LICENSE_1_0.txt

- \ No newline at end of file diff --git a/src/auto_timers.cpp b/src/auto_timers.cpp new file mode 100644 index 0000000..e99e5f7 --- /dev/null +++ b/src/auto_timers.cpp @@ -0,0 +1,130 @@ +// boost auto_cpu_timer.cpp -----------------------------------------------------// + +// Copyright Beman Dawes 1994-2006, 2011 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt) + +//----------------------------------------------------------------------------// + +// define BOOST_TIMER_SOURCE so that knows +// the library is being built (possibly exporting rather than importing code) +#define BOOST_TIMER_SOURCE + +#include +#include +#include +#include +#include + +using boost::timer::nanosecond_type; +using boost::timer::cpu_times; +using boost::system::error_code; + +# if defined(BOOST_WINDOWS_API) +# include +# elif defined(BOOST_POSIX_API) +# include +# else +# error unknown API +# endif + +namespace +{ + // cpu_timer helpers ---------------------------------------------------------------// + + void show_time(const cpu_times& times, + std::ostream& os, const std::string& fmt, short places) + // NOTE WELL: Will truncate least-significant digits to LDBL_DIG, which may + // be as low as 10, although will be 15 for many common platforms. + { + if (places > 9) + places = 9; + else if (places < 0) + places = boost::timer::default_places; + + boost::io::ios_flags_saver ifs(os); + boost::io::ios_precision_saver ips(os); + os.setf(std::ios_base::fixed, std::ios_base::floatfield); + os.precision(places); + + const long double sec = 1000000000.0L; + nanosecond_type total = times.system + times.user; + long double wall_sec = times.wall / sec; + long double total_sec = total / sec; + + for (const char* format = fmt.c_str(); *format; ++format) + { + if (*format != '%' || !*(format+1) || !std::strchr("wustp", *(format+1))) + os << *format; // anything except % followed by a valid format character + // gets sent to the output stream + else + { + ++format; + switch (*format) + { + case 'w': + os << times.wall / sec; + break; + case 'u': + os << times.user / sec; + break; + case 's': + os << times.system / sec; + break; + case 't': + os << total / sec; + break; + case 'p': + os.precision(1); + if (wall_sec > 0.001L && total_sec > 0.001L) + os << (total_sec/wall_sec) * 100.0; + else + os << "n/a"; + os.precision(places); + break; + } + } + } + } + +} // unnamed namespace + +namespace boost +{ + namespace timer + { + // format ------------------------------------------------------------------------// + + BOOST_TIMER_DECL + std::string format(const cpu_times& times, short places, const std::string& fmt) + { + std::stringstream ss; + show_time(times, ss, fmt, places); + return ss.str(); + } + + // auto_cpu_timer ----------------------------------------------------------------// + + void auto_cpu_timer::report() + { + show_time(stop(), m_os, m_format, m_places); + resume(); + } + + auto_cpu_timer::~auto_cpu_timer() + { + if (!is_stopped()) + { + try + { + report(); + } + catch (...) // eat any exceptions + { + } + } + } + + } // namespace timer +} // namespace boost diff --git a/src/auto_timers_construction.cpp b/src/auto_timers_construction.cpp new file mode 100644 index 0000000..85fcaf3 --- /dev/null +++ b/src/auto_timers_construction.cpp @@ -0,0 +1,37 @@ +// boost auto_timers_construction.cpp ------------------------------------------------// + +// Copyright Beman Dawes 2007, 2011 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/timer for documentation. + +//--------------------------------------------------------------------------------------// + +// These constructors are in a separate file so that this translation unit will +// not be linked in except when one of the constructors is actually used. This +// is important since header is required, and it incurs the cost of +// the standard stream objects even if they are not used. + +//--------------------------------------------------------------------------------------// + +// define BOOST_TIMER_SOURCE so that knows +// the library is being built (possibly exporting rather than importing code) +#define BOOST_TIMER_SOURCE + +#include +#include + +namespace boost +{ + namespace timer + { + auto_cpu_timer::auto_cpu_timer(short places, const std::string& format) + : m_places(places), m_os(std::cout), m_format(format) { start(); } + + auto_cpu_timer::auto_cpu_timer(const std::string& format) + : m_places(default_places), m_os(std::cout), m_format(format) { start(); } + + } // namespace timer +} // namespace boost diff --git a/src/cpu_timer.cpp b/src/cpu_timer.cpp new file mode 100644 index 0000000..91a45e0 --- /dev/null +++ b/src/cpu_timer.cpp @@ -0,0 +1,163 @@ +// boost cpu_timer.cpp ---------------------------------------------------------------// + +// Copyright Beman Dawes 1994-2006, 2011 + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/timer for documentation. + +//--------------------------------------------------------------------------------------// + +// define BOOST_TIMER_SOURCE so that knows +// the library is being built (possibly exporting rather than importing code) +#define BOOST_TIMER_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +# if defined(BOOST_WINDOWS_API) +# include +# elif defined(BOOST_POSIX_API) +# include +# include +# else +# error unknown API +# endif + +using boost::system::error_code; + +namespace +{ + +# if defined(BOOST_POSIX_API) + boost::int_least64_t tick_factor() // multiplier to convert ticks + // to nanoseconds; -1 if unknown + { + static boost::int_least64_t tick_factor = 0; + if (!tick_factor) + { + if ((tick_factor = ::sysconf(_SC_CLK_TCK)) <= 0) + tick_factor = -1; + else + { + assert(tick_factor <= 1000000000LL); // logic doesn't handle large ticks + tick_factor = 1000000000LL / tick_factor; // compute factor + if (!tick_factor) + tick_factor = -1; + } + } + return tick_factor; + } +# endif + + void get_cpu_times(boost::timer::cpu_times& current) + { + boost::chrono::duration + x (boost::chrono::high_resolution_clock::now().time_since_epoch()); + current.wall = x.count(); + +# if defined(BOOST_WINDOWS_API) + + FILETIME creation, exit; + if (::GetProcessTimes(::GetCurrentProcess(), &creation, &exit, + (LPFILETIME)¤t.system, (LPFILETIME)¤t.user)) + { + current.user *= 100; // Windows uses 100 nanosecond ticks + current.system *= 100; + } + else + { + current.system = current.user = boost::timer::nanosecond_type(-1); + } +# else + tms tm; + clock_t c = ::times(&tm); + if (c == -1) // error + { + current.system = current.user = boost::timer::nanosecond_type(-1); + } + else + { + current.system = boost::timer::nanosecond_type(tm.tms_stime + tm.tms_cstime); + current.user = boost::timer::nanosecond_type(tm.tms_utime + tm.tms_cutime); + boost::int_least64_t factor; + if ((factor = tick_factor()) != -1) + { + current.user *= factor; + current.system *= factor; + } + else + { + current.user = current.system = boost::timer::nanosecond_type(-1); + } + } +# endif + } + +} // unnamed namespace + +namespace boost +{ + namespace timer + { + + BOOST_TIMER_DECL + const std::string& default_format() + { + static std::string fmt(" %ws wall, %us user + %ss system = %ts CPU (%p%)\n"); + return fmt; + } + + // cpu_timer ---------------------------------------------------------------------// + + void cpu_timer::start() + { + m_is_stopped = false; + get_cpu_times(m_times); + } + + const cpu_times& cpu_timer::stop() + { + if (is_stopped()) + return m_times; + m_is_stopped = true; + + cpu_times current; + get_cpu_times(current); + m_times.wall = (current.wall - m_times.wall); + m_times.user = (current.user - m_times.user); + m_times.system = (current.system - m_times.system); + return m_times; + } + + cpu_times cpu_timer::elapsed() const + { + if (is_stopped()) + return m_times; + cpu_times current; + get_cpu_times(current); + current.wall -= m_times.wall; + current.user -= m_times.user; + current.system -= m_times.system; + return current; + } + + void cpu_timer::resume() + { + if (is_stopped()) + { + cpu_times current (m_times); + start(); + m_times.wall -= current.wall; + m_times.user -= current.user; + m_times.system -= current.system; + } + } + } // namespace timer +} // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 96641b6..6210c7d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,9 +1,39 @@ -#~ Copyright Rene Rivera 2008 -#~ Distributed under the Boost Software License, Version 1.0. -#~ (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# Boost Timer Library test Jamfile -import testing ; +# Copyright Beman Dawes 2003, 2006, 2011 -test-suite timer - : [ compile timer_test.cpp ] +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +# See library home page at http://www.boost.org/libs/timer + +project + : requirements + /boost/timer//boost_timer + msvc:on ; + + test-suite "timer" + : + [ run ../example/auto_cpu_timer_example.cpp + : # command line + : # input files + : always_show_run_output # requirements + ] + [ run cpu_timer_info.cpp + : # command line + : # input files + : always_show_run_output # requirements + ] + [ run cpu_timer_test.cpp + : # command line + : # input files + : always_show_run_output # requirements + ] + [ run ../example/timex.cpp + : echo "Hello, world" + : + : always_show_run_output + ] + [ compile original_timer_test.cpp ] + ; diff --git a/test/cpu_timer_info.cpp b/test/cpu_timer_info.cpp new file mode 100644 index 0000000..11e722c --- /dev/null +++ b/test/cpu_timer_info.cpp @@ -0,0 +1,75 @@ +// boost cpu_timer_info.cpp ----------------------------------------------------------// + +// Copyright Beman Dawes 2011 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See http://www.boost.org/libs/timer for documentation. + +#include +#include +#include +#include // for atol() +#include +#include + +using boost::timer::nanosecond_type; +using boost::timer::cpu_times; +using boost::timer::cpu_timer; +using boost::timer::auto_cpu_timer; +using std::cout; using std::endl; + +int cpp_main( int argc, char * argv[] ) +{ + cout << '\n'; + cout << "For cpu_times.wall, the underlying clock " + << (boost::chrono::high_resolution_clock::is_steady + ? "is steady. " + : "is not steady. " + ) + << "Steady clocks are defined by C++11 as clocks for which values " + "of time_point never decrease as physical time advances and for " + "which values of time_point advance at a steady rate relative to " + "real time. That is, the clock may not be adjusted.\n\n"; + + cpu_times start_time; + start_time.clear(); + cpu_times current_time; + + { + cpu_timer cpu; + cout << "measure boost::timer::cpu_timer resolution for user time..." + << endl; + for (int i = 0; i < 3; ++i) + { + cpu.start(); + start_time = cpu.elapsed(); + current_time.user = start_time.user; + while (current_time.user == start_time.user) + { + current_time = cpu.elapsed(); + } + cout << current_time.user - start_time.user << "ns\n"; + } + } + + { + cpu_timer cpu; + cout << "measure boost::timer::cpu_timer resolution for wall-clock time..." + << endl; + for (int i = 0; i < 100; ++i) + { + cpu.start(); + start_time.wall = cpu.elapsed().wall; + current_time.wall = start_time.wall; + while (current_time.wall == start_time.wall) + { + current_time.wall = cpu.elapsed().wall; + } + cout << current_time.wall - start_time.wall << "ns "; + } + } + return 0; +} + diff --git a/test/cpu_timer_test.cpp b/test/cpu_timer_test.cpp new file mode 100644 index 0000000..1127343 --- /dev/null +++ b/test/cpu_timer_test.cpp @@ -0,0 +1,133 @@ +// boost timer_test.cpp --------------------------------------------------------------// + +// Copyright Beman Dawes 2006, 2011 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See http://www.boost.org/libs/timer for documentation. + +#include +#include +#include +#include // for atol() +#include +#include + +namespace old +{ +#include +} + +using std::string; +using std::cout; +using std::endl; +using boost::timer::nanosecond_type; +using boost::timer::cpu_times; +using boost::timer::format; +using boost::timer::cpu_timer; +using boost::timer::auto_cpu_timer; + +namespace +{ + void format_test() + { + cout << "format test..." << endl; + + cpu_times times; + times.wall = 5123456789LL; + times.user = 2123456789LL; + times.system = 1234567890LL; + + cout << " times.wall is " << times.wall << '\n'; + cout << " times.user is " << times.user << '\n'; + cout << " times.system is " << times.system << '\n'; + cout << " user+system is " << times.user + times.system << '\n'; + cout << " format(times, 9) output: " << format(times, 9); + + BOOST_TEST_EQ(format(times, 9), + string(" 5.123456789s wall, 2.123456789s user + 1.234567890s system = 3.358024679s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 8), + string(" 5.12345679s wall, 2.12345679s user + 1.23456789s system = 3.35802468s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 7), + string(" 5.1234568s wall, 2.1234568s user + 1.2345679s system = 3.3580247s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 6), + string(" 5.123457s wall, 2.123457s user + 1.234568s system = 3.358025s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 5), + string(" 5.12346s wall, 2.12346s user + 1.23457s system = 3.35802s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 4), + string(" 5.1235s wall, 2.1235s user + 1.2346s system = 3.3580s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 3), + string(" 5.123s wall, 2.123s user + 1.235s system = 3.358s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 2), + string(" 5.12s wall, 2.12s user + 1.23s system = 3.36s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 1), + string(" 5.1s wall, 2.1s user + 1.2s system = 3.4s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 0), + string(" 5s wall, 2s user + 1s system = 3s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, 10), + string(" 5.123456789s wall, 2.123456789s user + 1.234567890s system = 3.358024679s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times, -1), + string(" 5.123457s wall, 2.123457s user + 1.234568s system = 3.358025s CPU (65.5%)\n")); + BOOST_TEST_EQ(format(times), + string(" 5.123457s wall, 2.123457s user + 1.234568s system = 3.358025s CPU (65.5%)\n")); + + BOOST_TEST_EQ(format(times, 5, " %w, %u, %s, %t, %%p%"), + string(" 5.12346, 2.12346, 1.23457, 3.35802, %65.5%")); + + BOOST_TEST_EQ(format(times, 5, "boo"), string("boo")); + + cout << " format test complete" << endl; + } + + void std_c_consistency_test() + { + cout << "C library consistency test..." << endl; + + // This test is designed to account for C timer resolution and for the possibility + // that another active process may take up a lot of time. + + cout << " CLOCKS_PER_SEC is " << CLOCKS_PER_SEC << endl; + + double c_t_elapsed; + + old::boost::timer c_t; + cpu_timer t; + + while (t.elapsed().wall < 1000000000) {} + + t.stop(); + c_t_elapsed = c_t.elapsed(); + + cout.setf(std::ios_base::fixed, std::ios_base::floatfield); + cout.precision(9); + + cout << " c_t_elapsed is " << c_t_elapsed << endl; + cout << " t.elapsed().wall is " << t.elapsed().wall << endl; + cout << " t.elapsed().wall/1000000000.0L is " + << t.elapsed().wall/1000000000.0L << endl; + cout << " c_t_elapsed * 1.05L is " + << c_t_elapsed * 1.05L << endl; + + BOOST_TEST(t.elapsed().wall >= 1000000000); + + BOOST_TEST(t.elapsed().wall / 1000000000.0L <= c_t_elapsed * 1.05L); + + cout << " C library consistency test complete" << endl; + } + + +} // unnamed namespace + +//--------------------------------------------------------------------------------------// + +int cpp_main(int argc, char * argv[]) +{ + cout << "---------- timer_test ----------\n"; + + format_test(); + std_c_consistency_test(); + + return ::boost::report_errors(); +} + diff --git a/test/timer_test.cpp b/test/original_timer_test.cpp similarity index 100% rename from test/timer_test.cpp rename to test/original_timer_test.cpp