1.1 --- a/src/core/system-wall-clock-ms.h Mon Oct 26 11:26:35 2009 -0700
1.2 +++ b/src/core/system-wall-clock-ms.h Mon Oct 26 14:50:38 2009 -0700
1.3 @@ -21,13 +21,13 @@
1.4 #ifndef SYSTEM_WALL_CLOCK_MS_H
1.5 #define SYSTEM_WALL_CLOCK_MS_H
1.6
1.7 +#include <stdint.h>
1.8 +
1.9 namespace ns3 {
1.10
1.11 /**
1.12 - * \brief measure wall-clock time in milliseconds
1.13 -
1.14 - * \todo This class exists also in non-unix systems but is not
1.15 - * implemented and always return zero as measurd time.
1.16 + * \brief measure elapsed time in milliseconds
1.17 + *
1.18 */
1.19 class SystemWallClockMs {
1.20 public:
1.21 @@ -45,24 +45,32 @@
1.22 *
1.23 * It is possible to start a new measurement with ns3::SystemWallClockMs::Start
1.24 * after this method returns.
1.25 + *
1.26 + * Returns int64_t to avoid dependency on clock_t in ns-3 code.
1.27 */
1.28 - unsigned long long End (void);
1.29 + int64_t End (void);
1.30
1.31 /**
1.32 * \returns the measured elapsed wall clock time (in milliseconds) since
1.33 * ns3::SystemWallClockMs::Start was invoked.
1.34 + *
1.35 + * Returns int64_t to avoid dependency on clock_t in ns-3 code.
1.36 */
1.37 - double GetElapsedReal (void) const;
1.38 + int64_t GetElapsedReal (void) const;
1.39 /**
1.40 * \returns the measured elapsed 'user' wall clock time (in milliseconds) since
1.41 * ns3::SystemWallClockMs::Start was invoked.
1.42 + *
1.43 + * Returns int64_t to avoid dependency on clock_t in ns-3 code.
1.44 */
1.45 - double GetElapsedUser (void) const;
1.46 + int64_t GetElapsedUser (void) const;
1.47 /**
1.48 * \returns the measured elapsed 'system' wall clock time (in milliseconds) since
1.49 * ns3::SystemWallClockMs::Start was invoked.
1.50 + *
1.51 + * Returns int64_t to avoid dependency on clock_t in ns-3 code.
1.52 */
1.53 - double GetElapsedSystem (void) const;
1.54 + int64_t GetElapsedSystem (void) const;
1.55
1.56 private:
1.57 class SystemWallClockMsPrivate *m_priv;
2.1 --- a/src/core/test.cc Mon Oct 26 11:26:35 2009 -0700
2.2 +++ b/src/core/test.cc Mon Oct 26 14:50:38 2009 -0700
2.3 @@ -262,7 +262,7 @@
2.4 void
2.5 TestCase::DoReportStart (void)
2.6 {
2.7 - m_clock.Start ();
2.8 + m_msClock.Start ();
2.9
2.10 if (m_ofs == 0)
2.11 {
2.12 @@ -319,18 +319,21 @@
2.13 void
2.14 TestCase::DoReportEnd (void)
2.15 {
2.16 - m_clock.End ();
2.17 + m_msClock.End ();
2.18 +
2.19 if (m_ofs == 0)
2.20 {
2.21 return;
2.22 }
2.23
2.24 - (*m_ofs).precision (2);
2.25 + (*m_ofs).precision (3);
2.26 *m_ofs << std::fixed;
2.27
2.28 - *m_ofs << " <CaseTime>" << "real " << m_clock.GetElapsedReal () * 1e-3
2.29 - << " user " << m_clock.GetElapsedUser () * 1e-3
2.30 - << " system " << m_clock.GetElapsedSystem () * 1e-3
2.31 + const double MS_PER_SEC = 1000.;
2.32 +
2.33 + *m_ofs << " <CaseTime>" << "real " << m_msClock.GetElapsedReal () / MS_PER_SEC
2.34 + << " user " << m_msClock.GetElapsedUser () / MS_PER_SEC
2.35 + << " system " << m_msClock.GetElapsedSystem () / MS_PER_SEC
2.36 << "</CaseTime>" << std::endl;
2.37
2.38 *m_ofs << " </TestCase>" << std::endl;
2.39 @@ -515,7 +518,7 @@
2.40 void
2.41 TestSuite::DoReportStart (void)
2.42 {
2.43 - m_clock.Start ();
2.44 + m_msClock.Start ();
2.45
2.46 if (m_ofs == 0)
2.47 {
2.48 @@ -548,19 +551,21 @@
2.49 void
2.50 TestSuite::DoReportEnd (void)
2.51 {
2.52 - m_clock.End ();
2.53 + m_msClock.End ();
2.54
2.55 if (m_ofs == 0)
2.56 {
2.57 return;
2.58 }
2.59
2.60 - (*m_ofs).precision (2);
2.61 + (*m_ofs).precision (3);
2.62 *m_ofs << std::fixed;
2.63
2.64 - *m_ofs << " <SuiteTime>" << "real " << m_clock.GetElapsedReal () * 1e-3
2.65 - << " user " << m_clock.GetElapsedUser () * 1e-3
2.66 - << " system " << m_clock.GetElapsedSystem () * 1e-3
2.67 + const double MS_PER_SEC = 1000.;
2.68 +
2.69 + *m_ofs << " <SuiteTime>" << "real " << m_msClock.GetElapsedReal () / MS_PER_SEC
2.70 + << " user " << m_msClock.GetElapsedUser () / MS_PER_SEC
2.71 + << " system " << m_msClock.GetElapsedSystem () / MS_PER_SEC
2.72 << "</SuiteTime>" << std::endl;
2.73
2.74 *m_ofs << "</TestSuite>" << std::endl;
3.1 --- a/src/core/test.h Mon Oct 26 11:26:35 2009 -0700
3.2 +++ b/src/core/test.h Mon Oct 26 14:50:38 2009 -0700
3.3 @@ -824,7 +824,7 @@
3.4 TestCase (TestCase& tc);
3.5 TestCase& operator= (TestCase& tc);
3.6
3.7 - SystemWallClockMs m_clock;
3.8 + SystemWallClockMs m_msClock;
3.9 std::string m_name;
3.10 bool m_verbose;
3.11 bool m_continueOnFailure;
3.12 @@ -1059,7 +1059,7 @@
3.13 TestSuite (TestSuite& ts);
3.14 TestSuite& operator= (TestSuite& ts);
3.15
3.16 - SystemWallClockMs m_clock;
3.17 + SystemWallClockMs m_msClock;
3.18 std::string m_name;
3.19 bool m_verbose;
3.20 bool m_continueOnFailure;
4.1 --- a/src/core/unix-system-wall-clock-ms.cc Mon Oct 26 11:26:35 2009 -0700
4.2 +++ b/src/core/unix-system-wall-clock-ms.cc Mon Oct 26 14:50:38 2009 -0700
4.3 @@ -19,26 +19,25 @@
4.4 */
4.5
4.6 #include "system-wall-clock-ms.h"
4.7 +#include "abort.h"
4.8 #include <sys/times.h>
4.9 -#include <unistd.h>
4.10 -#include <limits.h>
4.11
4.12 namespace ns3 {
4.13
4.14 class SystemWallClockMsPrivate {
4.15 public:
4.16 void Start (void);
4.17 - unsigned long long End (void);
4.18 - double GetElapsedReal (void) const;
4.19 - double GetElapsedUser (void) const;
4.20 - double GetElapsedSystem (void) const;
4.21 + int64_t End (void);
4.22 + int64_t GetElapsedReal (void) const;
4.23 + int64_t GetElapsedUser (void) const;
4.24 + int64_t GetElapsedSystem (void) const;
4.25
4.26 private:
4.27 struct tms m_startTimes;
4.28 clock_t m_startTime;
4.29 - double m_elapsedReal;
4.30 - double m_elapsedUser;
4.31 - double m_elapsedSystem;
4.32 + int64_t m_elapsedReal;
4.33 + int64_t m_elapsedUser;
4.34 + int64_t m_elapsedSystem;
4.35 };
4.36
4.37 void
4.38 @@ -47,34 +46,73 @@
4.39 m_startTime = times (&m_startTimes);
4.40 }
4.41
4.42 -unsigned long long
4.43 +int64_t
4.44 SystemWallClockMsPrivate::End (void)
4.45 {
4.46 - static long ticksPerSecond = sysconf (_SC_CLK_TCK);
4.47 + //
4.48 + // We need to return the number of milliseconds that have elapsed in some
4.49 + // reasonably portable way. The underlying function that we will use returns
4.50 + // a number of elapsed ticks. We can look up the number of ticks per second
4.51 + // from the system configuration.
4.52 + //
4.53 + // Conceptually, we need to find the number of elapsed clock ticks and then
4.54 + // multiply the result by the milliseconds per clock tick (or divide by clock
4.55 + // ticks per millisecond). Integer dividing by clock ticks per millisecond
4.56 + // is bad since this number is fractional on most machines and would result
4.57 + // in divide by zero errors due to integer rounding.
4.58 + //
4.59 + // Multiplying by milliseconds per clock tick works up to a clock resolution
4.60 + // of 1000 ticks per second. If we go past this point, we begin to get zero
4.61 + // elapsed times when millisecondsPerTick becomes fractional and another
4.62 + // rounding error appears.
4.63 + //
4.64 + // So rounding errors using integers can bite you from both direction. Since
4.65 + // all of our targets have math coprocessors, why not just use doubles
4.66 + // internally? Works fine, lasts a long time.
4.67 + //
4.68 + // If millisecondsPerTick becomes fractional, and an elapsed time greater than
4.69 + // a milliscond is measured, the function will work as expected. If an elapsed
4.70 + // time is measured that turns out to be less than a millisecond, we'll just
4.71 + // return zero which would, I think, also will be expected.
4.72 + //
4.73 + static int64_t ticksPerSecond = sysconf (_SC_CLK_TCK);
4.74 + static double millisecondsPerTick = 1000. / ticksPerSecond;
4.75 +
4.76 + //
4.77 + // If sysconf () fails, we have no idea how to do the required conversion to ms.
4.78 + //
4.79 + NS_ABORT_MSG_IF (ticksPerSecond == -1, "SystemWallClockMsPrivate(): Cannot sysconf (_SC_CLK_TCK)");
4.80
4.81 struct tms endTimes;
4.82 clock_t endTime = times (&endTimes);
4.83
4.84 - m_elapsedReal = 1e3 * static_cast<double> (endTime - m_startTime) / ticksPerSecond;
4.85 - m_elapsedUser = 1e3 * static_cast<double> (endTimes.tms_utime - m_startTimes.tms_utime) / ticksPerSecond;
4.86 - m_elapsedSystem = 1e3 * static_cast<double> (endTimes.tms_stime - m_startTimes.tms_stime) / ticksPerSecond;
4.87 + double tmp;
4.88 +
4.89 + tmp = static_cast<double> (endTime - m_startTime) * millisecondsPerTick;
4.90 + m_elapsedReal = static_cast<int64_t> (tmp);
4.91 +
4.92 + tmp = static_cast<double> (endTimes.tms_utime - m_startTimes.tms_utime) * millisecondsPerTick;
4.93 + m_elapsedUser = static_cast<int64_t> (tmp);
4.94 +
4.95 + tmp = static_cast<double> (endTimes.tms_stime - m_startTimes.tms_stime) * millisecondsPerTick;
4.96 + m_elapsedSystem = static_cast<int64_t> (tmp);
4.97
4.98 return m_elapsedReal;
4.99 }
4.100
4.101 -double
4.102 +int64_t
4.103 SystemWallClockMsPrivate::GetElapsedReal (void) const
4.104 {
4.105 return m_elapsedReal;
4.106 }
4.107
4.108 -double
4.109 +int64_t
4.110 SystemWallClockMsPrivate::GetElapsedUser (void) const
4.111 {
4.112 return m_elapsedUser;
4.113 }
4.114
4.115 -double
4.116 +int64_t
4.117 SystemWallClockMsPrivate::GetElapsedSystem (void) const
4.118 {
4.119 return m_elapsedSystem;
4.120 @@ -95,25 +133,26 @@
4.121 {
4.122 m_priv->Start ();
4.123 }
4.124 -unsigned long long
4.125 +
4.126 +int64_t
4.127 SystemWallClockMs::End (void)
4.128 {
4.129 return m_priv->End ();
4.130 }
4.131
4.132 -double
4.133 +int64_t
4.134 SystemWallClockMs::GetElapsedReal (void) const
4.135 {
4.136 return m_priv->GetElapsedReal ();
4.137 }
4.138
4.139 -double
4.140 +int64_t
4.141 SystemWallClockMs::GetElapsedUser (void) const
4.142 {
4.143 return m_priv->GetElapsedUser ();
4.144 }
4.145
4.146 -double
4.147 +int64_t
4.148 SystemWallClockMs::GetElapsedSystem (void) const
4.149 {
4.150 return m_priv->GetElapsedSystem ();
5.1 --- a/src/core/win32-system-wall-clock-ms.cc Mon Oct 26 11:26:35 2009 -0700
5.2 +++ b/src/core/win32-system-wall-clock-ms.cc Mon Oct 26 14:50:38 2009 -0700
5.3 @@ -20,26 +20,97 @@
5.4
5.5 #include "system-wall-clock-ms.h"
5.6
5.7 +#include <time.h>
5.8 +
5.9 namespace ns3 {
5.10
5.11 class SystemWallClockMsPrivate {
5.12 public:
5.13 void Start (void);
5.14 - unsigned long long End (void);
5.15 + int64_t End (void);
5.16 + int64_t GetElapsedReal (void) const;
5.17 + int64_t GetElapsedUser (void) const;
5.18 + int64_t GetElapsedSystem (void) const;
5.19 +
5.20 private:
5.21 + clock_t m_startTime;
5.22 + int64_t m_elapsedReal;
5.23 + int64_t m_elapsedUser;
5.24 + int64_t m_elapsedSystem;
5.25 };
5.26
5.27 void
5.28 SystemWallClockMsPrivate::Start (void)
5.29 {
5.30 + m_startTime = clock ();
5.31 }
5.32
5.33 -unsigned long long
5.34 +int64_t
5.35 SystemWallClockMsPrivate::End (void)
5.36 {
5.37 - return 0;
5.38 + //
5.39 + // We need to return the number of milliseconds that have elapsed in some
5.40 + // reasonably portable way. The underlying function that we will use returns
5.41 + // a number of elapsed ticks. We can look up the number of ticks per second
5.42 + // from the system configuration.
5.43 + //
5.44 + // Conceptually, we need to find the number of elapsed clock ticks and then
5.45 + // multiply the result by the milliseconds per clock tick (or just as easily
5.46 + // divide by clock ticks per millisecond). Integer dividing by clock ticks
5.47 + // per millisecond is bad since this number is fractional on most machines
5.48 + // and would result in divide by zero errors due to integer rounding.
5.49 + //
5.50 + // Multiplying by milliseconds per clock tick works up to a clock resolution
5.51 + // of 1000 ticks per second. If we go past this point, we begin to get zero
5.52 + // elapsed times when millisecondsPerTick becomes fractional and another
5.53 + // rounding error appears.
5.54 + //
5.55 + // So rounding errors using integers can bite you from two direction. Since
5.56 + // all of our targets have math coprocessors, why not just use doubles
5.57 + // internally? Works fine, lasts a long time.
5.58 + //
5.59 + // If millisecondsPerTick becomes fractional, and an elapsed time greater than
5.60 + // a milliscond is measured, the function will work as expected. If an elapsed
5.61 + // time is measured that turns out to be less than a millisecond, we'll just
5.62 + // return zero which would, I think, also will be expected.
5.63 + //
5.64 + static int64_t ticksPerSecond = CLOCKS_PER_SEC;
5.65 + static double millisecondsPerTick = 1000. / ticksPerSecond;
5.66 +
5.67 + clock_t endTime = clock ();
5.68 +
5.69 + double tmp;
5.70 +
5.71 + tmp = static_cast<double> (endTime - m_startTime) * millisecondsPerTick;
5.72 + m_elapsedReal = static_cast<int64_t> (tmp);
5.73 +
5.74 + //
5.75 + // Nothing like this in MinGW, for example.
5.76 + //
5.77 + m_elapsedUser = 0;
5.78 + m_elapsedSystem = 0;
5.79 +
5.80 + return m_elapsedReal;
5.81 }
5.82
5.83 +int64_t
5.84 +SystemWallClockMsPrivate::GetElapsedReal (void) const
5.85 +{
5.86 + return m_elapsedReal;
5.87 +}
5.88 +
5.89 +int64_t
5.90 +SystemWallClockMsPrivate::GetElapsedUser (void) const
5.91 +{
5.92 + return m_elapsedUser;
5.93 +}
5.94 +
5.95 +int64_t
5.96 +SystemWallClockMsPrivate::GetElapsedSystem (void) const
5.97 +{
5.98 + return m_elapsedSystem;
5.99 +}
5.100 +
5.101 SystemWallClockMs::SystemWallClockMs ()
5.102 : m_priv (new SystemWallClockMsPrivate ())
5.103 {}
5.104 @@ -55,28 +126,29 @@
5.105 {
5.106 m_priv->Start ();
5.107 }
5.108 -unsigned long long
5.109 +
5.110 +int64_t
5.111 SystemWallClockMs::End (void)
5.112 {
5.113 return m_priv->End ();
5.114 }
5.115
5.116 -double
5.117 +int64_t
5.118 SystemWallClockMs::GetElapsedReal (void) const
5.119 {
5.120 - return 0;
5.121 + return m_priv->GetElapsedReal ();
5.122 }
5.123
5.124 -double
5.125 +int64_t
5.126 SystemWallClockMs::GetElapsedUser (void) const
5.127 {
5.128 - return 0;
5.129 + return m_priv->GetElapsedUser ();
5.130 }
5.131
5.132 -double
5.133 +int64_t
5.134 SystemWallClockMs::GetElapsedSystem (void) const
5.135 {
5.136 - return 0;
5.137 + return m_priv->GetElapsedSystem ();
5.138 }
5.139
5.140 }; // namespace ns3
6.1 --- a/utils/bench-packets.cc Mon Oct 26 11:26:35 2009 -0700
6.2 +++ b/utils/bench-packets.cc Mon Oct 26 14:50:38 2009 -0700
6.3 @@ -248,7 +248,7 @@
6.4 SystemWallClockMs time;
6.5 time.Start ();
6.6 (*bench) (n);
6.7 - unsigned long long deltaMs = time.End ();
6.8 + uint64_t deltaMs = time.End ();
6.9 double ps = n;
6.10 ps *= 1000;
6.11 ps /= deltaMs;