Skip to content

Instantly share code, notes, and snippets.

@AndreyChechel
Last active July 19, 2017 20:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndreyChechel/007ef230eafc50d4c81bf6fe850f0fc9 to your computer and use it in GitHub Desktop.
Save AndreyChechel/007ef230eafc50d4c81bf6fe850f0fc9 to your computer and use it in GitHub Desktop.
Performance analysis of approaches to clone a Stack<T> instance
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
public class Program
{
public void Main()
{
// The code below compares performance and memory consumption
// for different approaches to clone a Stack<T> instance.
RunPerformanceTests();
// Uncomment to run Memory tests. This may take a few minutes to finish.
// "precision" argument specifies allowed error (number of elements).
//RunMaxSizeTests(1000);
}
private void RunPerformanceTests()
{
var stack = FillStackWithData(10000000);
var tests = new[] {
new { Name = "Clone1", Run = new Action(() => stack.Clone1()) },
new { Name = "Clone2", Run = new Action(() => stack.Clone2()) },
new { Name = "Clone3", Run = new Action(() => stack.Clone3()) },
new { Name = "Clone4", Run = new Action(() => stack.Clone4()) }
};
var sw = new Stopwatch();
foreach (var test in tests)
{
GC.Collect();
sw.Restart();
test.Run();
Console.WriteLine($"{test.Name}: {sw.Elapsed.TotalMilliseconds} ms");
}
}
private void RunMaxSizeTests(int precision)
{
var tests = new[] {
new { Name = "Clone1", Run = (Expression<Func<Stack<int>, Stack<int>>>)(s => s.Clone1()) },
new { Name = "Clone2", Run = (Expression<Func<Stack<int>, Stack<int>>>)(s => s.Clone2()) },
new { Name = "Clone3", Run = (Expression<Func<Stack<int>, Stack<int>>>)(s => s.Clone3()) },
new { Name = "Clone4", Run = (Expression<Func<Stack<int>, Stack<int>>>)(s => s.Clone4()) }
};
var sw = new Stopwatch();
foreach (var test in tests)
{
var maxSize = FindMaxStackSize(precision, test.Run);
Console.WriteLine($"{test.Name}: {maxSize} elements");
}
}
private Stack<int> FillStackWithData(int size)
{
var stack = new Stack<int>();
for (int i = 0; i < size; i++)
{
stack.Push(i);
}
return stack;
}
private int FindMaxStackSize(int precision, Expression<Func<Stack<int>, Stack<int>>> cloneExpr)
{
var step = 10000000; // initial step value
var size = step;
while (step > precision)
{
try
{
GC.Collect();
var stack = new Stack<int>();
for (int i = 0; i < size; i++)
{
stack.Push(i);
}
var cloneFn = cloneExpr.Compile();
cloneFn(stack);
size += step;
}
catch (OutOfMemoryException)
{
step /= 2;
size -= step;
}
}
return size;
}
}
public static class StackExtensions
{
public static Stack<T> Clone1<T>(this Stack<T> original)
{
return new Stack<T>(new Stack<T>(original));
}
public static Stack<T> Clone2<T>(this Stack<T> original)
{
return new Stack<T>(original.Reverse());
}
public static Stack<T> Clone3<T>(this Stack<T> original)
{
var arr = original.ToArray();
Array.Reverse(arr);
return new Stack<T>(arr);
}
public static Stack<T> Clone4<T>(this Stack<T> original)
{
var arr = new T[original.Count];
original.CopyTo(arr, 0);
Array.Reverse(arr);
return new Stack<T>(arr);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment