From e17fe2e7cf69e73c788a3f1e85aa768be14e980e Mon Sep 17 00:00:00 2001 From: Craig Dowell Date: Mon, 26 Oct 2009 14:50:38 -0700 Subject: [PATCH] make win32 compile again --- src/core/system-wall-clock-ms.h | 24 ++++--- src/core/test.cc | 29 ++++---- src/core/test.h | 4 +- src/core/unix-system-wall-clock-ms.cc | 81 +++++++++++++++++------ src/core/win32-system-wall-clock-ms.cc | 92 +++++++++++++++++++++++--- utils/bench-packets.cc | 2 +- 6 files changed, 178 insertions(+), 54 deletions(-) diff --git a/src/core/system-wall-clock-ms.h b/src/core/system-wall-clock-ms.h index 9cca3ca38..2895f3dd8 100644 --- a/src/core/system-wall-clock-ms.h +++ b/src/core/system-wall-clock-ms.h @@ -21,13 +21,13 @@ #ifndef SYSTEM_WALL_CLOCK_MS_H #define SYSTEM_WALL_CLOCK_MS_H +#include + namespace ns3 { /** - * \brief measure wall-clock time in milliseconds - - * \todo This class exists also in non-unix systems but is not - * implemented and always return zero as measurd time. + * \brief measure elapsed time in milliseconds + * */ class SystemWallClockMs { public: @@ -45,24 +45,32 @@ public: * * It is possible to start a new measurement with ns3::SystemWallClockMs::Start * after this method returns. + * + * Returns int64_t to avoid dependency on clock_t in ns-3 code. */ - unsigned long long End (void); + int64_t End (void); /** * \returns the measured elapsed wall clock time (in milliseconds) since * ns3::SystemWallClockMs::Start was invoked. + * + * Returns int64_t to avoid dependency on clock_t in ns-3 code. */ - double GetElapsedReal (void) const; + int64_t GetElapsedReal (void) const; /** * \returns the measured elapsed 'user' wall clock time (in milliseconds) since * ns3::SystemWallClockMs::Start was invoked. + * + * Returns int64_t to avoid dependency on clock_t in ns-3 code. */ - double GetElapsedUser (void) const; + int64_t GetElapsedUser (void) const; /** * \returns the measured elapsed 'system' wall clock time (in milliseconds) since * ns3::SystemWallClockMs::Start was invoked. + * + * Returns int64_t to avoid dependency on clock_t in ns-3 code. */ - double GetElapsedSystem (void) const; + int64_t GetElapsedSystem (void) const; private: class SystemWallClockMsPrivate *m_priv; diff --git a/src/core/test.cc b/src/core/test.cc index 3b3a2db24..77d833651 100644 --- a/src/core/test.cc +++ b/src/core/test.cc @@ -262,7 +262,7 @@ TestCase::ContinueOnFailure (void) void TestCase::DoReportStart (void) { - m_clock.Start (); + m_msClock.Start (); if (m_ofs == 0) { @@ -319,18 +319,21 @@ TestCase::DoReportTestFailure ( void TestCase::DoReportEnd (void) { - m_clock.End (); + m_msClock.End (); + if (m_ofs == 0) { return; } - (*m_ofs).precision (2); + (*m_ofs).precision (3); *m_ofs << std::fixed; - *m_ofs << " " << "real " << m_clock.GetElapsedReal () * 1e-3 - << " user " << m_clock.GetElapsedUser () * 1e-3 - << " system " << m_clock.GetElapsedSystem () * 1e-3 + const double MS_PER_SEC = 1000.; + + *m_ofs << " " << "real " << m_msClock.GetElapsedReal () / MS_PER_SEC + << " user " << m_msClock.GetElapsedUser () / MS_PER_SEC + << " system " << m_msClock.GetElapsedSystem () / MS_PER_SEC << "" << std::endl; *m_ofs << " " << std::endl; @@ -515,7 +518,7 @@ TestSuite::ContinueOnFailure (void) void TestSuite::DoReportStart (void) { - m_clock.Start (); + m_msClock.Start (); if (m_ofs == 0) { @@ -548,19 +551,21 @@ TestSuite::DoReportSuccess (void) void TestSuite::DoReportEnd (void) { - m_clock.End (); + m_msClock.End (); if (m_ofs == 0) { return; } - (*m_ofs).precision (2); + (*m_ofs).precision (3); *m_ofs << std::fixed; - *m_ofs << " " << "real " << m_clock.GetElapsedReal () * 1e-3 - << " user " << m_clock.GetElapsedUser () * 1e-3 - << " system " << m_clock.GetElapsedSystem () * 1e-3 + const double MS_PER_SEC = 1000.; + + *m_ofs << " " << "real " << m_msClock.GetElapsedReal () / MS_PER_SEC + << " user " << m_msClock.GetElapsedUser () / MS_PER_SEC + << " system " << m_msClock.GetElapsedSystem () / MS_PER_SEC << "" << std::endl; *m_ofs << "" << std::endl; diff --git a/src/core/test.h b/src/core/test.h index 1a6e77950..571578ff1 100644 --- a/src/core/test.h +++ b/src/core/test.h @@ -824,7 +824,7 @@ private: TestCase (TestCase& tc); TestCase& operator= (TestCase& tc); - SystemWallClockMs m_clock; + SystemWallClockMs m_msClock; std::string m_name; bool m_verbose; bool m_continueOnFailure; @@ -1059,7 +1059,7 @@ private: TestSuite (TestSuite& ts); TestSuite& operator= (TestSuite& ts); - SystemWallClockMs m_clock; + SystemWallClockMs m_msClock; std::string m_name; bool m_verbose; bool m_continueOnFailure; diff --git a/src/core/unix-system-wall-clock-ms.cc b/src/core/unix-system-wall-clock-ms.cc index cfe53932f..78c83b566 100644 --- a/src/core/unix-system-wall-clock-ms.cc +++ b/src/core/unix-system-wall-clock-ms.cc @@ -19,26 +19,25 @@ */ #include "system-wall-clock-ms.h" +#include "abort.h" #include -#include -#include namespace ns3 { class SystemWallClockMsPrivate { public: void Start (void); - unsigned long long End (void); - double GetElapsedReal (void) const; - double GetElapsedUser (void) const; - double GetElapsedSystem (void) const; + int64_t End (void); + int64_t GetElapsedReal (void) const; + int64_t GetElapsedUser (void) const; + int64_t GetElapsedSystem (void) const; private: struct tms m_startTimes; clock_t m_startTime; - double m_elapsedReal; - double m_elapsedUser; - double m_elapsedSystem; + int64_t m_elapsedReal; + int64_t m_elapsedUser; + int64_t m_elapsedSystem; }; void @@ -47,34 +46,73 @@ SystemWallClockMsPrivate::Start (void) m_startTime = times (&m_startTimes); } -unsigned long long +int64_t SystemWallClockMsPrivate::End (void) { - static long ticksPerSecond = sysconf (_SC_CLK_TCK); + // + // We need to return the number of milliseconds that have elapsed in some + // reasonably portable way. The underlying function that we will use returns + // a number of elapsed ticks. We can look up the number of ticks per second + // from the system configuration. + // + // Conceptually, we need to find the number of elapsed clock ticks and then + // multiply the result by the milliseconds per clock tick (or divide by clock + // ticks per millisecond). Integer dividing by clock ticks per millisecond + // is bad since this number is fractional on most machines and would result + // in divide by zero errors due to integer rounding. + // + // Multiplying by milliseconds per clock tick works up to a clock resolution + // of 1000 ticks per second. If we go past this point, we begin to get zero + // elapsed times when millisecondsPerTick becomes fractional and another + // rounding error appears. + // + // So rounding errors using integers can bite you from both direction. Since + // all of our targets have math coprocessors, why not just use doubles + // internally? Works fine, lasts a long time. + // + // If millisecondsPerTick becomes fractional, and an elapsed time greater than + // a milliscond is measured, the function will work as expected. If an elapsed + // time is measured that turns out to be less than a millisecond, we'll just + // return zero which would, I think, also will be expected. + // + static int64_t ticksPerSecond = sysconf (_SC_CLK_TCK); + static double millisecondsPerTick = 1000. / ticksPerSecond; + + // + // If sysconf () fails, we have no idea how to do the required conversion to ms. + // + NS_ABORT_MSG_IF (ticksPerSecond == -1, "SystemWallClockMsPrivate(): Cannot sysconf (_SC_CLK_TCK)"); struct tms endTimes; clock_t endTime = times (&endTimes); - m_elapsedReal = 1e3 * static_cast (endTime - m_startTime) / ticksPerSecond; - m_elapsedUser = 1e3 * static_cast (endTimes.tms_utime - m_startTimes.tms_utime) / ticksPerSecond; - m_elapsedSystem = 1e3 * static_cast (endTimes.tms_stime - m_startTimes.tms_stime) / ticksPerSecond; + double tmp; + + tmp = static_cast (endTime - m_startTime) * millisecondsPerTick; + m_elapsedReal = static_cast (tmp); + + tmp = static_cast (endTimes.tms_utime - m_startTimes.tms_utime) * millisecondsPerTick; + m_elapsedUser = static_cast (tmp); + + tmp = static_cast (endTimes.tms_stime - m_startTimes.tms_stime) * millisecondsPerTick; + m_elapsedSystem = static_cast (tmp); return m_elapsedReal; } -double +int64_t SystemWallClockMsPrivate::GetElapsedReal (void) const { return m_elapsedReal; } -double +int64_t SystemWallClockMsPrivate::GetElapsedUser (void) const { return m_elapsedUser; } -double +int64_t SystemWallClockMsPrivate::GetElapsedSystem (void) const { return m_elapsedSystem; @@ -95,25 +133,26 @@ SystemWallClockMs::Start (void) { m_priv->Start (); } -unsigned long long + +int64_t SystemWallClockMs::End (void) { return m_priv->End (); } -double +int64_t SystemWallClockMs::GetElapsedReal (void) const { return m_priv->GetElapsedReal (); } -double +int64_t SystemWallClockMs::GetElapsedUser (void) const { return m_priv->GetElapsedUser (); } -double +int64_t SystemWallClockMs::GetElapsedSystem (void) const { return m_priv->GetElapsedSystem (); diff --git a/src/core/win32-system-wall-clock-ms.cc b/src/core/win32-system-wall-clock-ms.cc index c02f0f268..25046dbea 100644 --- a/src/core/win32-system-wall-clock-ms.cc +++ b/src/core/win32-system-wall-clock-ms.cc @@ -20,26 +20,97 @@ #include "system-wall-clock-ms.h" +#include + namespace ns3 { class SystemWallClockMsPrivate { public: void Start (void); - unsigned long long End (void); + int64_t End (void); + int64_t GetElapsedReal (void) const; + int64_t GetElapsedUser (void) const; + int64_t GetElapsedSystem (void) const; + private: + clock_t m_startTime; + int64_t m_elapsedReal; + int64_t m_elapsedUser; + int64_t m_elapsedSystem; }; void SystemWallClockMsPrivate::Start (void) { + m_startTime = clock (); } -unsigned long long +int64_t SystemWallClockMsPrivate::End (void) { - return 0; + // + // We need to return the number of milliseconds that have elapsed in some + // reasonably portable way. The underlying function that we will use returns + // a number of elapsed ticks. We can look up the number of ticks per second + // from the system configuration. + // + // Conceptually, we need to find the number of elapsed clock ticks and then + // multiply the result by the milliseconds per clock tick (or just as easily + // divide by clock ticks per millisecond). Integer dividing by clock ticks + // per millisecond is bad since this number is fractional on most machines + // and would result in divide by zero errors due to integer rounding. + // + // Multiplying by milliseconds per clock tick works up to a clock resolution + // of 1000 ticks per second. If we go past this point, we begin to get zero + // elapsed times when millisecondsPerTick becomes fractional and another + // rounding error appears. + // + // So rounding errors using integers can bite you from two direction. Since + // all of our targets have math coprocessors, why not just use doubles + // internally? Works fine, lasts a long time. + // + // If millisecondsPerTick becomes fractional, and an elapsed time greater than + // a milliscond is measured, the function will work as expected. If an elapsed + // time is measured that turns out to be less than a millisecond, we'll just + // return zero which would, I think, also will be expected. + // + static int64_t ticksPerSecond = CLOCKS_PER_SEC; + static double millisecondsPerTick = 1000. / ticksPerSecond; + + clock_t endTime = clock (); + + double tmp; + + tmp = static_cast (endTime - m_startTime) * millisecondsPerTick; + m_elapsedReal = static_cast (tmp); + + // + // Nothing like this in MinGW, for example. + // + m_elapsedUser = 0; + m_elapsedSystem = 0; + + return m_elapsedReal; } +int64_t +SystemWallClockMsPrivate::GetElapsedReal (void) const +{ + return m_elapsedReal; +} + +int64_t +SystemWallClockMsPrivate::GetElapsedUser (void) const +{ + return m_elapsedUser; +} + +int64_t +SystemWallClockMsPrivate::GetElapsedSystem (void) const +{ + return m_elapsedSystem; +} + SystemWallClockMs::SystemWallClockMs () : m_priv (new SystemWallClockMsPrivate ()) {} @@ -55,28 +126,29 @@ SystemWallClockMs::Start (void) { m_priv->Start (); } -unsigned long long + +int64_t SystemWallClockMs::End (void) { return m_priv->End (); } -double +int64_t SystemWallClockMs::GetElapsedReal (void) const { - return 0; + return m_priv->GetElapsedReal (); } -double +int64_t SystemWallClockMs::GetElapsedUser (void) const { - return 0; + return m_priv->GetElapsedUser (); } -double +int64_t SystemWallClockMs::GetElapsedSystem (void) const { - return 0; + return m_priv->GetElapsedSystem (); } }; // namespace ns3 diff --git a/utils/bench-packets.cc b/utils/bench-packets.cc index ff9ef71ae..ad951072c 100644 --- a/utils/bench-packets.cc +++ b/utils/bench-packets.cc @@ -248,7 +248,7 @@ runBench (void (*bench) (uint32_t), uint32_t n, char const *name) SystemWallClockMs time; time.Start (); (*bench) (n); - unsigned long long deltaMs = time.End (); + uint64_t deltaMs = time.End (); double ps = n; ps *= 1000; ps /= deltaMs;