//C#/CSClasses/Stopwatch.cs //Matthew Ellison // Created: 08-21-20 //Modified: 08-21-20 //This file contains a class that is used to time the execution time of other programs /* Copyright (C) 2020 Matthew Ellison This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ namespace mee{ public class Stopwatch{ //Variables private readonly System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); //The stopwatch that is used private enum TIME_RESOLUTION{ NANOSECOND, MICROSECOND, MILLISECOND, SECOND, MINUTE, HOUR, ERROR }; private const int NUM_TO_RUN = 100000; private readonly long nanosecPerTick = 1000000000L / System.Diagnostics.Stopwatch.Frequency; //Functions //Constructor makes sure all values are set to defaults public Stopwatch(){ } //Simultates starting a stopwatch public void Start(){ stopwatch.Start(); } //Simulates stopping a stopwatch public void Stop(){ stopwatch.Stop(); } //Resets all the variables in teh stopwatch public void Reset(){ stopwatch.Reset(); } //Returns the timer in nanoseconds public decimal GetNano(){ return (decimal)nanosecPerTick * (decimal)stopwatch.ElapsedTicks; } //Returns the timer in microseconds public decimal GetMicro(){ return GetNano() / 1000m; } //Returns the timer in milliseconds public decimal GetMilli(){ return GetNano() / 1000000m; } //Returns the timer in seconds public decimal GetSecond(){ return GetNano() / 1000000000m; } //Returns the timer in minutes public decimal GetMinute(){ return GetNano() / 60000000000m; } //Returns the timer in hours public decimal GetHour(){ return GetNano() / 3600000000000m; } //Returns the timer as a string at the 'best' resolution. (Goal is xxx.xxx) public string GetStr(){ //Get the current duration from time return GetStr(GetNano()); } //Returns a string of the decimal value passed in (assuming the value in nanoseconds) public static string GetStr(decimal nanoseconds){ decimal duration = nanoseconds; //Reduce the number to the appropriate number of digits. (xxx.x) //This loop works down to seconds TIME_RESOLUTION resolution; for(resolution = TIME_RESOLUTION.NANOSECOND;(resolution < TIME_RESOLUTION.SECOND) && (duration >= 1000);++resolution){ duration /= 1000; } //Check if the duration needs reduced to minutes if((duration >= 120) && (resolution == TIME_RESOLUTION.SECOND)){ //Reduce to mintues duration /= 60; ++resolution; //Check if the duration needs reduced to hours if(duration >= 60){ //Reduce to hours duration /= 60; ++resolution; } } //Turn the number into a string string time = duration.ToString("C3").Substring(1); //Tack on the appropriate suffix for resolution switch(resolution){ case TIME_RESOLUTION.NANOSECOND: time += " nanoseconds"; break; case TIME_RESOLUTION.MICROSECOND: time += " microseconds"; break; case TIME_RESOLUTION.MILLISECOND: time += " milliseconds"; break; case TIME_RESOLUTION.SECOND: time += " seconds"; break; case TIME_RESOLUTION.MINUTE: time += " minutes"; break; case TIME_RESOLUTION.HOUR: time += " hours"; break; case TIME_RESOLUTION.ERROR: default: time = "There was an error computing the time"; break; //TODO: This should throw an exception instead } //Return the string return time; } //Overrides default tostring. returns getStr public override string ToString(){ return GetStr(); } //Tests public static void Main(){ System.Console.WriteLine("Testing start/stop"); TestStartStop(); System.Console.WriteLine("start/stop completed successfully"); System.Console.WriteLine("Testing conversion"); TestConversion(); System.Console.WriteLine("conversion test completed successfully"); System.Console.WriteLine("Testing stringConversion"); TestStringConversion(); System.Console.WriteLine("stringConversion completed successfully"); } public static void TestStartStop(){ Stopwatch timer = new Stopwatch(); timer.Start(); timer.Stop(); //If it gets here without throwing an exception everything went well } public static void TestConversion(){ Stopwatch timer = new Stopwatch(); int sum = 0; //Start the timer timer.Start(); //Do something to run some time for(int cnt = 0;cnt < NUM_TO_RUN;++cnt){ sum += cnt; } //Stop the timer timer.Stop(); //Assert something so the sum isn't ignored during compile System.Diagnostics.Debug.Assert(sum != 0); //Check that the different resolutions work out correctly decimal nano = timer.GetNano(); System.Diagnostics.Debug.Assert(timer.GetMicro() == (nano / 1000m), "Micro resolution test failed"); System.Diagnostics.Debug.Assert(timer.GetMilli() == (nano / 1000000m), "Milli resolution test failed"); System.Diagnostics.Debug.Assert(timer.GetSecond() == (nano / 1000000000m), "Second resolution test failed"); System.Diagnostics.Debug.Assert(timer.GetMinute() == (nano / 60000000000m), "Minute resolution test failed"); System.Diagnostics.Debug.Assert(timer.GetHour() == (nano / 3600000000000m), "Hour resolution test failed"); } public static void TestStringConversion(){ //Test nanoseconds string results = Stopwatch.GetStr(1.0m); System.Diagnostics.Debug.Assert(results == "1.000 nanoseconds", "Failed nanoseconds: " + results); //Test microseconds results = Stopwatch.GetStr(1.0e3m); System.Diagnostics.Debug.Assert(results == "1.00 microsesconds", "Failed microseconds: " + results); //Test milliseconds results = Stopwatch.GetStr(1.0e6m); System.Diagnostics.Debug.Assert(results == "1.00 milliseconds", "Failed milliseconds: " + results); //Test seconds results = Stopwatch.GetStr(1.0e9m); System.Diagnostics.Debug.Assert(results == "1.00 seconds", "Failed seconds: " + results); //Test minutes results = Stopwatch.GetStr(1.0e12m); System.Diagnostics.Debug.Assert(results == "1.00 minutes", "Failed minutes: " + results); //Test hours results = Stopwatch.GetStr(1.0e13m); System.Diagnostics.Debug.Assert(results == "1.00 hours", "Failed hours: " + results); } } }