static void Main() { int reps = 5000000; Console.WriteLine("LINQ's Last extension method will enumerate over the *entire* collection giving"); Console.WriteLine("a time complexity of O(n) regardless of the data structure. This is due to the"); Console.WriteLine("\"one size fits all\" approach of LINQ. SortedDictionary supplies no optimized"); Console.WriteLine("implementation of Last. Also, SortedDictionary does not supply any optimized"); Console.WriteLine("way of performing queries based on a key range. Again, the time complexity of"); Console.WriteLine("such an operation is O(n).\n"); var sd = new SortedDictionary <int, int>(); Console.Write("Loading SortedDictionary with " + reps + " elements:\n\nLoad time = "); Stopwatch watch1 = new Stopwatch(); watch1.Reset(); watch1.Start(); for (int i = 0; i < reps; ++i) { sd.Add(i, -i); } var time11 = watch1.ElapsedMilliseconds; var last1 = sd.Last(); var time12 = watch1.ElapsedMilliseconds; Console.WriteLine(time11 + "ms"); Console.WriteLine("Last time = " + (time12 - time11) + "ms"); //// Console.WriteLine("\nRankedDictionary has its own implementation of Last() which does not suffer the"); Console.WriteLine("performance hit that SortedDictionary.Last() does. RankedDictionary also"); Console.WriteLine("supports optimized range queries with its ElementsFrom(TKey) and"); Console.WriteLine("ElementsBetween(TKey,TKey) enumerators.\n"); var bt = new RankedDictionary <int, int>(); Console.Write("Loading RankedDictionary with " + reps + " elements:\n\nLoad time = "); Stopwatch watch2 = new Stopwatch(); watch2.Reset(); watch2.Start(); for (int i = 0; i < reps; ++i) { bt.Add(i, -i); } var time21 = watch2.ElapsedMilliseconds; var lastKV = bt.Last(); var time22 = watch2.ElapsedMilliseconds; // Range query: Sum the middle 100 values. var rangeVals = bt.ElementsBetween(reps / 2 - 50, reps / 2 + 50).Sum(x => x.Value); var time23 = watch2.ElapsedMilliseconds; Console.WriteLine(time21 + "ms"); Console.WriteLine("Last time = " + (time22 - time21) + "ms"); Console.WriteLine("Range time = " + (time23 - time22) + "ms"); #if DEBUG bt.SanityCheck(); Console.WriteLine(); Console.Write("---- height = " + bt.GetHeight()); Console.Write(", branch fill = " + bt.BranchSlotsUsed * 100 / bt.BranchSlotCount + "%"); Console.WriteLine(", leaf fill = " + bt.LeafSlotsUsed * 100 / bt.LeafSlotCount + "% ----"); #endif }
static void Main() { int reps = 10000000; var sl = new SortedList <int, int>(); var rd = new RankedDictionary <int, int>(); var watch = new Stopwatch(); Console.WriteLine("Loading SortedList..."); for (int ix = 0; ix <= reps; ++ix) { sl.Add(ix, -ix); } Console.WriteLine("Loading RankedDictionary..."); for (int i = 0; i <= reps; ++i) { rd.Add(i, -i); } Thread.Sleep(500); Console.WriteLine("Get Element at Index"); Console.WriteLine("Time in Milliseconds"); Console.WriteLine("Index by " + (reps / 10)); Console.WriteLine("Count;row;SortedList;RankedDictionary"); for (int row = 0, ix = 0; ix <= reps; ix += reps / 10) { watch.Reset(); watch.Start(); var slPair = sl.ElementAt(ix); var slTime = watch.ElapsedMilliseconds; if (slPair.Key != -slPair.Value) { Console.Write("FAIL"); } watch.Reset(); watch.Start(); var rdPair = rd.ElementAt(ix); var rdTime = watch.ElapsedMilliseconds; if (rdPair.Key != -rdPair.Value) { Console.Write("FAIL"); } var lx = String.Format($"{ix,9};{row,4};{slTime,5};{rdTime,5}"); if (row > 0) { Console.WriteLine(lx); } ++row; } watch.Reset(); watch.Start(); var slPair2 = sl.Last(); var slTime2 = watch.ElapsedMilliseconds; if (slPair2.Key != -slPair2.Value) { Console.Write("FAIL"); } watch.Reset(); watch.Start(); var rdPair2 = rd.Last(); var rdTime2 = watch.ElapsedMilliseconds; if (rdPair2.Key != -rdPair2.Value) { Console.Write("FAIL"); } var lx2 = String.Format($"{reps,9};Last;{slTime2,5};{rdTime2,5}"); Console.WriteLine(lx2); }