public static void ConvexHull() { int[] testSizes = new int[] { 12345, 100, 316, 1000, 3160, 10000, 31600, 100000, 316000, 1000000, 3160000, 10000000 }; for (int iter = 0; iter < testSizes.Length; iter++) { Random r = new Random(); List <PointD> points = new List <PointD>(testSizes[iter]); for (int i = 0; i < points.Capacity; i++) { double size = r.NextDouble(); double ang = r.NextDouble() * (Math.PI * 2); points.Add(new PointD(size * Math.Cos(ang), size * Math.Sin(ang))); } // Plus: test sorting time to learn how much of the time is spent sorting var points2 = new List <PointD>(points); EzStopwatch timer = new EzStopwatch(true); points2.Sort((a, b) => a.X == b.X ? a.Y.CompareTo(b.Y) : (a.X < b.X ? -1 : 1)); Stopwatch timer2 = new Stopwatch(); timer2.Start(); int sortTime = timer.Restart(); IListSource <Point <double> > output = PointMath.ComputeConvexHull(points, true); int hullTime = timer.Millisec; Console.WriteLine("{0:c} (ticks:{1,10} freq:{2})", timer2.Elapsed, timer2.ElapsedTicks, Stopwatch.Frequency); if (iter == 0) { continue; // first iteration primes the JIT/caches } Console.WriteLine("Convex hull of {0,8} points took {1} ms ({2} ms for sorting step). Output has {3} points.", testSizes[iter], hullTime, sortTime, output.Count); } }
/// <summary>Runs a piece of code one or more times and records the time taken.</summary> /// <remarks>Garbage-collects before the test(s) if DoGC is true.</remarks> public void RunCore(int minMillisec, Func <Benchmarker, object> code, int loopTimes, bool noGC, EzStopwatch totalTime) { // Give the test as good a chance as possible to avoid garbage collection if (DoGC && !noGC) { GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); } var oldTimer = _currentTimer; try { _currentTimer = new EzStopwatch(true); do { _currentTimer.Restart(); object userData = null; for (int i = 0; i < loopTimes; i++) { userData = code(this); } double millisec = _currentTimer.Millisec; if (userData as string != DiscardResult) { Tally(ActiveBenchmarkName, millisec, userData); } } while (totalTime.Millisec < minMillisec); } finally { _currentTimer = oldTimer; } }
public static int Fill <T>(T[] keys, IDictionary <T, object> dict, object value) { EzStopwatch t = new EzStopwatch(true); for (int i = 0; i < keys.Length; i++) { dict[keys[i]] = value; } return(t.Millisec); }
public override void Visit(Alts alts) { _currentAlts = alts; KthSet[] firstSets = LLPG.ComputeFirstSets(alts); if (LLPG.Verbosity > 0) { var sb = new StringBuilder(); for (int i = 0; i < firstSets.Length; i++) { if (firstSets[i].Alt == -1 || LLPG.Verbosity > 2) { if (sb.Length != 0) { sb.Append('\n'); } sb.AppendFormat("First set for {0}: {1}", firstSets[i].Alt == -1 ? "exit" : "alt #" + (firstSets[i].Alt + 1), firstSets[i]); } } if (sb.Length != 0) { LLPG.Output(Verbose, alts, sb.ToString()); } } try { EzStopwatch timer = new EzStopwatch(true); alts.PredictionTree = ComputePredictionTree(firstSets); if (timer.Millisec > 500) { LLPG.Output(Warning, alts, "Slug? This took a long time to analyze: " + timer.Millisec + "ms"); } } catch (System.Threading.ThreadAbortException) { LLPG.Output(Error, alts, "ThreadAbortException in rule '" + _currentRule.Name + "'"); // user diagnostic throw; } if ((LLPG.Verbosity & 2) != 0) { LLPG.Output(Verbose, alts, "(unsimplified) " + alts.PredictionTree.ToString()); } SimplifyPredictionTree(alts.PredictionTree); AddElseCases(alts, alts.PredictionTree); _currentAlts = null; if ((LLPG.Verbosity & 1) != 0) { LLPG.Output(Verbose, alts, "(simplified) " + alts.PredictionTree.ToString()); } VisitChildrenOf(alts, true); }
public static int Scan(string[] words, int wordCount, int sectionSize, IDictionary <string, string>[] dicts) { EzStopwatch t = new EzStopwatch(true); int total = 0; for (int j = 0; j < sectionSize; j++) { for (int i = j, sec = 0; i < wordCount; i += sectionSize, sec++) { total += dicts[sec][words[i]].Length; } } return(t.Millisec); }
private static int Scan <T>(T[] keys, IDictionary <T, object> dict) { EzStopwatch t = new EzStopwatch(true); int irrelevant = 0; for (int i = 0; i < keys.Length; i++) { if (dict[keys[i]] != null) { irrelevant++; } } return(t.Millisec); }
/// <summary> /// Measures and records the time required for a given piece of code to run. /// Supports nested measurements. /// </summary> /// <param name="name">Name of a benchmark or sub-benchmark.</param> /// <param name="minMillisec">Minimum amount of time for which to run trials</param> /// <param name="code">Code to run.</param> /// <param name="loopTimes">Number of times to call code() in a loop; the /// entire loop counts as a single trial. This parameter is intended for /// small benchmarks that run for less than a few milliseconds; it is /// equivalent to having a for-loop inside your own code, but it should /// not be used for benchmarks that take less than one microsecond because /// the overhead of the virtual call to code() may influence the result of /// the benchmark.</param> /// <remarks>A benchmark method called by RunAllBenchmarks can call this /// method to run a sub-benchmark. A row on the results table will be created /// with both the name of the outer benchmark and the sub-benchmark. The /// outer benchmark's time will include time used by the sub-benchmark.</remarks> public int Run(string name, int minMillisec, Func <Benchmarker, object> code, int loopTimes = 1) { var oldActive = ActiveBenchmarkName; if (++_nestingDepth > 1) { ActiveBenchmarkName += ": "; } ActiveBenchmarkName += name; var totalTime = new EzStopwatch(true); try { RunCore(minMillisec, code, loopTimes, _nestingDepth > 1, totalTime); } catch (Exception ex) { Type excType = ex.GetType(); string msg = string.Format("{0}: {1}", ex.GetType().Name, ex.Message); while (ex.InnerException != null) { ex = ex.InnerException; msg += string.Format("\n Inner {0}: {1} ", ex.GetType().Name, ex.Message); if (excType == typeof(TargetInvocationException)) { excType = ex.GetType(); } } int count; _errors.TryGetValue(msg, out count); _errors[msg] = count + 1; TallyError(ActiveBenchmarkName, excType.Name); } finally { ActiveBenchmarkName = oldActive; _nestingDepth--; } return(totalTime.Millisec); }
public static int Fill(string[] words, int wordCount, int sectionSize, out IDictionary <string, string>[] dicts, Func <IDictionary <string, string> > factory) { Debug.Assert(sectionSize > 0); dicts = new IDictionary <string, string> [(wordCount - 1) / sectionSize + 1]; for (int sec = 0; sec < dicts.Length; sec++) { dicts[sec] = factory(); } EzStopwatch t = new EzStopwatch(true); for (int j = 0; j < sectionSize; j++) { for (int i = j, sec = 0; i < wordCount; i += sectionSize, sec++) { dicts[sec][words[i]] = words[i]; } } return(t.Millisec); }
public override void Visit(Alts alts) { _currentAlts = alts; KthSet[] firstSets = LLPG.ComputeFirstSets(alts); if (LLPG.Verbosity > 0) { var sb = new StringBuilder(); for (int i = 0; i < firstSets.Length; i++) { if (firstSets[i].Alt == -1 || LLPG.Verbosity > 2) { if (sb.Length != 0) sb.Append('\n'); sb.AppendFormat("First set for {0}: {1}", firstSets[i].Alt == -1 ? "exit" : "alt #" + (firstSets[i].Alt + 1), firstSets[i]); } } if (sb.Length != 0) LLPG.Output(Verbose, alts, sb.ToString()); } try { EzStopwatch TEMP = new EzStopwatch(true); alts.PredictionTree = ComputePredictionTree(firstSets); if (TEMP.Millisec > 500) LLPG.Output(Warning, alts, "Slug? This took a long time to analyze: " + TEMP.Millisec + "ms"); } catch (System.Threading.ThreadAbortException) { LLPG.Output(Error, alts, "ThreadAbortException in rule '" + _currentRule.Name + "'"); // user diagnostic throw; } if ((LLPG.Verbosity & 2) != 0) LLPG.Output(Verbose, alts, "(unsimplified) " + alts.PredictionTree.ToString()); SimplifyPredictionTree(alts.PredictionTree); AddElseCases(alts, alts.PredictionTree); _currentAlts = null; if ((LLPG.Verbosity & 1) != 0) LLPG.Output(Verbose, alts, "(simplified) " + alts.PredictionTree.ToString()); VisitChildrenOf(alts, true); }
public static void StringBenchmarkLine(string name, string[] words, int sectionSize, int reps, bool optimizeTrie, int wordCount) { int dictFillTime = 0, sdicFillTime = 0, trieFillTime = 0; int dictScanTime = 0, sdicScanTime = 0, trieScanTime = 0; long dictMemory = 0, sdicMemory = 0, trieMemory = 0; for (int rep = 0; rep < reps; rep++) { IDictionary <string, string>[] dicts = null, sdics = null, tries; GC.Collect(); if (!optimizeTrie) { // Each line where we optimize the trie is paired with another // line where we don't; there is no need to repeat the non-trie // benchmarks. dictFillTime += Fill(words, wordCount, sectionSize, out dicts, delegate() { return(new Dictionary <string, string>()); }); sdicFillTime += Fill(words, wordCount, sectionSize, out sdics, delegate() { return(new SortedDictionary <string, string>(StringComparer.Ordinal)); }); } trieFillTime += Fill(words, wordCount, sectionSize, out tries, delegate() { return(new CPStringTrie <string>()); }); if (optimizeTrie) { EzStopwatch t = new EzStopwatch(true); for (int i = 0; i < tries.Length; i++) { tries[i] = ((CPStringTrie <string>)tries[i]).Clone(); } trieFillTime += t.Millisec; } if (!optimizeTrie) { for (int i = 0; i < dicts.Length; i++) { dictMemory += CountMemoryUsage((Dictionary <string, string>)dicts[i], 4, 4); } for (int i = 0; i < sdics.Length; i++) { sdicMemory += CountMemoryUsage((SortedDictionary <string, string>)sdics[i], 4, 4); } } for (int i = 0; i < tries.Length; i++) { trieMemory += ((CPStringTrie <string>)tries[i]).CountMemoryUsage(4); } Scramble(words, wordCount, sectionSize); GC.Collect(); if (!optimizeTrie) { dictScanTime += Scan(words, wordCount, sectionSize, dicts); sdicScanTime += Scan(words, wordCount, sectionSize, sdics); } trieScanTime += Scan(words, wordCount, sectionSize, tries); } // A CPStringTrie encodes its keys directly into the tree so that no // separate memory is required to hold the keys. Therefore, if you want // to compare the memory use of Dictionary and CPStringTrie, you should // normally count the size of the keys against the Dictionary, but not // against the trie. // // In this contrived example, however, the values are the same as the // keys, so no memory is saved by encoding the keys in the trie. int keyMemory = 0; for (int i = 0; i < wordCount; i++) { // Note: I'm guessing the overhead of System.String. I assume each // string has a 12-byte header (8-byte object header plus Length) // and a null terminator (for native interop). keyMemory += 16 + (words[i].Length & ~1) * 2; } if (name != null) { Debug.Assert(reps > 0); double dictMB = (double)dictMemory / (1024 * 1024) / reps; double sdicMB = (double)sdicMemory / (1024 * 1024) / reps; double trieMB = (double)trieMemory / (1024 * 1024) / reps; double keyMB = (double)keyMemory / (1024 * 1024); string info0 = string.Format("{0,-20}{1,2} {2,8} ", name, reps, sectionSize); string info1 = string.Format("{0,4}ms {1,4}ms {2,4:#0.0}M+{3,4:#0.0}M ", dictFillTime / reps, dictScanTime / reps, dictMB, keyMB); string info2 = string.Format("{0,5}ms {1,4}ms {2,4:#0.0}M+{3,4:#0.0}M ", sdicFillTime / reps, sdicScanTime / reps, sdicMB, keyMB); string info3 = string.Format("{0,5}ms {1,5}ms {2,4:#0.0}M", trieFillTime / reps, trieScanTime / reps, trieMB); if (optimizeTrie) { info1 = " --ms --ms -- M+ -- M "; info2 = " -- ms -- ms -- M+ -- M "; } Console.WriteLine(info0 + info1 + info2 + info3); } }