GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
timer.hpp
1 /**
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 
24 #ifndef GRAPHLAB_TIMER_HPP
25 #define GRAPHLAB_TIMER_HPP
26 
27 #include <sys/time.h>
28 #include <stdio.h>
29 
30 #include <iostream>
31 
32 namespace graphlab {
33  /**
34  * \ingroup util
35  *
36  * \brief A simple class that can be used for benchmarking/timing up
37  * to microsecond resolution.
38  *
39  * Standard Usage
40  * =================
41  *
42  * The timer is used by calling \ref graphlab::timer::start and then
43  * by getting the current time since start by calling
44  * \ref graphlab::timer::current_time.
45  *
46  * For example:
47  *
48  * \code
49  * #include <graphlab.hpp>
50  *
51  *
52  * graphlab::timer timer;
53  * timer.start();
54  * // do something
55  * std::cout << "Elapsed time: " << timer.current_time() << std::endl;
56  * \endcode
57  *
58  * Fast approximate time
59  * ====================
60  *
61  * Calling current item in a tight loop can be costly and so we
62  * provide a faster less accurate timing primitive which reads a
63  * local time variable that is updated roughly every 100 millisecond.
64  * These are the \ref graphlab::timer::approx_time_seconds and
65  * \ref graphlab::timer::approx_time_millis.
66  */
67  class timer {
68  private:
69  /**
70  * \brief The internal start time for this timer object
71  */
72  timeval start_time_;
73  public:
74  /**
75  * \brief The timer starts on construction but can be restarted by
76  * calling \ref graphlab::timer::start.
77  */
78  inline timer() { start(); }
79 
80  /**
81  * \brief Reset the timer.
82  */
83  inline void start() { gettimeofday(&start_time_, NULL); }
84 
85  /**
86  * \brief Returns the elapsed time in seconds since
87  * \ref graphlab::timer::start was last called.
88  *
89  * @return time in seconds since \ref graphlab::timer::start was called.
90  */
91  inline double current_time() const {
92  timeval current_time;
93  gettimeofday(&current_time, NULL);
94  double answer =
95  // (current_time.tv_sec + ((double)current_time.tv_usec)/1.0E6) -
96  // (start_time_.tv_sec + ((double)start_time_.tv_usec)/1.0E6);
97  (double)(current_time.tv_sec - start_time_.tv_sec) +
98  ((double)(current_time.tv_usec - start_time_.tv_usec))/1.0E6;
99  return answer;
100  } // end of current_time
101 
102  /**
103  * \brief Returns the elapsed time in milliseconds since
104  * \ref graphlab::timer::start was last called.
105  *
106  * @return time in milliseconds since \ref graphlab::timer::start was called.
107  */
108  inline double current_time_millis() const { return current_time() * 1000; }
109 
110  /**
111  * \brief Get the number of seconds (as a floating point value)
112  * since the Unix Epoch.
113  */
114  static double sec_of_day() {
115  timeval current_time;
116  gettimeofday(&current_time, NULL);
117  double answer =
118  (double)current_time.tv_sec + ((double)current_time.tv_usec)/1.0E6;
119  return answer;
120  } // end of sec_of_day
121 
122  /**
123  * \brief Returns only the micro-second component of the
124  * time since the Unix Epoch.
125  */
126  static size_t usec_of_day() {
127  timeval current_time;
128  gettimeofday(&current_time, NULL);
129  size_t answer =
130  (size_t)current_time.tv_sec * 1000000 + (size_t)current_time.tv_usec;
131  return answer;
132  } // end of usec_of_day
133 
134  /**
135  * \brief Returns the time since program start.
136  *
137  * This value is only updated once every 100ms and is therefore
138  * approximate (but fast).
139  */
140  static float approx_time_seconds();
141 
142  /**
143  * \brief Returns the time since program start.
144  *
145  * This value is only updated once every 100ms and is therefore
146  * approximate (but fast).
147  */
148  static size_t approx_time_millis();
149 
150  /**
151  * Sleeps for sleeplen seconds
152  */
153  static void sleep(size_t sleeplen);
154 
155  /**
156  * Sleeps for sleeplen milliseconds.
157  */
158  static void sleep_ms(size_t sleeplen);
159  }; // end of Timer
160 
161 
162  unsigned long long estimate_ticks_per_second();
163 
164  #if defined(__i386__)
165  static inline unsigned long long rdtsc(void)
166  {
167  unsigned long long int x;
168  __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
169  return x;
170  }
171  #elif defined(__x86_64__)
172  static inline unsigned long long rdtsc(void)
173  {
174  unsigned hi, lo;
175  __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
176  return ( (unsigned long long)lo) | ( ((unsigned long long)hi)<<32 );
177  }
178  #else
179  static inline unsigned long long rdtsc(void) {
180  return 0;
181  }
182  #endif
183 
184 
185 } // end of graphlab namespace
186 
187 /**
188  * Convenience function. Allows you to call "cout << ti" where ti is
189  * a timer object and it will print the number of seconds elapsed
190  * since ti.start() was called.
191  */
192 std::ostream& operator<<(std::ostream& out, const graphlab::timer& t);
193 
194 
195 #endif
196