Tuesday, July 30, 2019

C# Human Readable Ticks with microsecond and nanosecond units



Here's a great modern was in C Sharp code to format Stopwatch 
Elapsed Ticks to be human readable number including micro and nanoseconds places. It uses StringBuilder (for speed) and Action delegate for string format variability. 



This implementation will leave units (day, hour, ...) parts if they are zero.  Say that microseconds is 0, it will not print 0µs place to save space of output string. 

  

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System; using System.Text; 
using System.Diagnostics; 
					
public static class Program
{
	/// <summary>
        ///  Human readable elapsed time Ticks using modern Action delegate, leaving out zero parts and variable length formatting 
        ///  https://metadataconsulting.blogspot.com/2019/07/C-Sharp-Human-Readable-Ticks-with-microsecond-and-nanosecond-units.html
        /// </summary>
        /// <param name="ticks">a long type</param>
        /// <returns>Human readable units place for microseconds & nanoseconds</returns>
        public static string HumanReadableTicks(this long ticks)
        {
            if (ticks == 0) return "0 ns";

            StringBuilder SB = new StringBuilder();

            Action<long, string, int> addUnittoSB =
            (val, displayunit, zeroplaces) =>
            {
                if (val > 0) //do not print this unit place if no value for it
                {
                    SB.AppendFormat(
                            " {0:DZ}X".Replace("X", displayunit)
                            .Replace("Z", zeroplaces.ToString())
                            , val
                        );
                }
            };

            var t = TimeSpan.FromTicks(ticks);

            //addActionToSringBuilder(timespan property, readable display displayunit, number of 0 placeholders)
            addUnittoSB((long)t.Days, "d", 1); //we have to convert to long to match Action signature
            addUnittoSB((long)t.Hours, "h", 1);
            addUnittoSB((long)t.Minutes, "m", 1);
            addUnittoSB((long)t.Seconds, "s", 1);
            addUnittoSB((long)t.Milliseconds, "ms", 3); //set milliseconds to 3 zero places (long) 
            addUnittoSB((long)((int)((t.TotalMilliseconds - (int)t.TotalMilliseconds) * 1000)), "µs", 3); //TotalMilliseconds is a double and has enough decimal places for accuracy here
            addUnittoSB((long)Convert.ToUInt64((((decimal)(t.Ticks * 100) % 1000))), "ns", 3); //1 tick is one hundred nanoseconds, get thousands place

            return SB.ToString().TrimStart();
        }
	
	public static void Main()
	{
		 Stopwatch sw = new Stopwatch();
		 Console.WriteLine("Human Readable Ticks program ran for"); 
		 sw.Start();
		 System.Threading.Thread.Sleep(1345);
		 sw.Stop();
		 Console.WriteLine(sw.ElapsedTicks + " ticks or "); 
		 Console.WriteLine(string.Format("{0:N0} nanoseconds (ns).",sw.ElapsedTicks*100));
		 Console.WriteLine("Human Readable format"); 
		 Console.WriteLine(sw.ElapsedTicks.HumanReadableTicks()); 
	}
}

No comments:

Post a Comment