using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.InteropServices; namespace foo { class C { private class PerformanceTime { [DllImport("Kernel32.dll")] private static extern bool QueryPerformanceCounter( out long lpPerformanceCount); [DllImport("Kernel32.dll")] private static extern bool QueryPerformanceFrequency( out long lpFrequency); private long freq; // Constructor public PerformanceTime() { if(QueryPerformanceFrequency(out freq) == false) { // not supported throw new Win32Exception(); } } public double CurrentSecond { get { long now; QueryPerformanceCounter(out now); return (double)(now) / freq; } } } public static void Main(string[] argv) { short s = 300; int i = 300; long l = 300; Console.WriteLine("----------- short: -----------"); Console.WriteLine(test(s)); Console.WriteLine("----------- int: -----------"); Console.WriteLine(test(i)); Console.WriteLine("----------- long: -----------"); Console.WriteLine(test(l)); return; } private static string test(T x) { string ret; const int trials = 100000; const int repeatCount = 50; PerformanceTime pt = new PerformanceTime(); double[] longerBucket = new double[repeatCount]; double[] bytesUsedBucket = new double[repeatCount]; for (int j = 0; j < repeatCount; j++) { Console.Write(j.ToString() + "\r"); GC.Collect(); // clean up any existing garbage double tick = pt.CurrentSecond; for (int i = 0; i < trials; i++) { string.Format("{0}", x); } long gc1 = GC.GetTotalMemory(false); GC.Collect(); // account for time garbage collection takes double elapsedNo = pt.CurrentSecond - tick; long gc2 = GC.GetTotalMemory(true); // elapsed time for this set of trials long bytesUsedNo = gc1 - gc2; GC.Collect(); // clean up any existing garbage tick = pt.CurrentSecond; for (int i = 0; i < trials; i++) { string.Format("{0}", x.ToString()); } gc1 = GC.GetTotalMemory(false); GC.Collect(); // account for time garbage collection takes double elapsed = pt.CurrentSecond - tick; gc2 = GC.GetTotalMemory(true); long bytesUsed = gc1 - gc2; longerBucket[j] = (elapsedNo - elapsed)/elapsed; bytesUsedBucket[j] = ((double) (bytesUsedNo - bytesUsed))/trials; // Console.WriteLine("No ToString: {0}us {1} bytes", // Math.Floor(elapsedNo*1000000), bytesUsedNo); // Console.WriteLine(" ToString: {0}us {1} bytes", // Math.Floor(elapsed*1000000), bytesUsed); // Console.WriteLine( // "No ToString {0}% longer and uses {1} bytes more memory/Format()", // Math.Floor(1000*longerBucket[j])/10, bytesUsedBucket[j]); } // Throw out the oddball trial results and get the average of the remaining double sd = StandardDeviation(longerBucket); double av = Average(longerBucket); double min = av - sd; double max = av + sd; List longer = new List(); foreach (double d in longerBucket) { if (min <= d && d <= max) { longer.Add(d); } } sd = StandardDeviation(bytesUsedBucket); av = Average(bytesUsedBucket); min = av - sd; max = av + sd; List used = new List(); foreach (double d in bytesUsedBucket) { if (min <= d && d <= max) { used.Add(d); } } ret = string.Format( "No ToString {0}% longer and uses {1} bytes more memory/Format()", Math.Floor(Average(longer.ToArray())*1000)/10, Average(used.ToArray())); return ret; } private static double StandardDeviation(double[] data) { double ret; if(data.Length > 1) { double totalVariance = 0; double average = Average(data); foreach (double d in data) { totalVariance += Math.Pow(d - average, 2); } ret = Math.Sqrt(totalVariance/data.Length); } else { ret = 0; } return ret; } private static double Average(double[] data) { double ret; if(data.Length > 0) { double total = 0; foreach(double d in data) { total += d; } ret = total/data.Length; } else { ret = 0; } return ret; } } }