-
-
Save benaadams/ba3c008a328f02c75663213cd9affa65 to your computer and use it in GitHub Desktop.
Simple IList performance benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Collections; | |
using System.Diagnostics; | |
using System.Runtime.CompilerServices; | |
namespace IListPerformance | |
{ | |
public class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
int iterations = 50000000; | |
int[] array = new int[iterations]; | |
List<int> list = new List<int>(array); | |
ArrayWrapperNonInlined wrapper2 = new ArrayWrapperNonInlined(array); | |
ArrayWrapper wrapper = new ArrayWrapper(array); | |
Console.WriteLine("Warming up..."); | |
for (int i = 0; i < 4; i++) | |
{ | |
SumArray(array); | |
SumIList(array); | |
SumArrayWrapper(wrapper); | |
SumArrayWrapper2(wrapper2); | |
SumList(list); | |
SumIList(list); | |
SumIList(wrapper); | |
SumGeneric(array); | |
SumGeneric(list); | |
SumGeneric(wrapper); | |
} | |
Console.WriteLine("Times are in milliseconds\n"); | |
RunTest(x => SumArray(x), array, "Array"); | |
RunTest(x => SumIList(x), array, "Array as IList"); | |
RunTest(x => SumArrayWrapper(x), wrapper, "ArrayWrapper"); | |
RunTest(x => SumArrayWrapper2(x), wrapper2, "ArrayWrapper Non-inlined"); | |
RunTest(x => SumList(x), list, "List"); | |
RunTest(x => SumIList(x), list, "List as IList"); | |
RunTest(x => SumIList(x), wrapper, "ArrayWrapper as IList"); | |
RunTest(x => SumGeneric(x), array, "Array as Generic"); | |
RunTest(x => SumGeneric(x), list, "List as Generic"); | |
RunTest(x => SumGeneric(x), wrapper, "ArrayWrapper as Generic"); | |
} | |
private static void RunTest<T>(Func<T, int> test, T array, string testName) | |
{ | |
Stopwatch watch = Stopwatch.StartNew(); | |
var val = test(array); | |
watch.Stop(); | |
Console.WriteLine($"{watch.ElapsedMilliseconds} \t {testName}"); | |
} | |
private static int SumArray(int[] array) | |
{ | |
int result = 0; | |
for (int i = 0; i < array.Length; i++) | |
result += array[i]; | |
return result; | |
} | |
private static int SumIList(IList<int> ilist) | |
{ | |
int result = 0; | |
var count = ilist.Count; | |
for (int i = 0; i < count; i++) | |
result += ilist[i]; | |
return result; | |
} | |
private static int SumList(List<int> list) | |
{ | |
int result = 0; | |
var count = list.Count; | |
for (int i = 0; i < count; i++) | |
result += list[i]; | |
return result; | |
} | |
private static int SumArrayWrapper(ArrayWrapper wrapper) | |
{ | |
int result = 0; | |
var count = wrapper.Count; | |
for (int i = 0; i < count; i++) | |
result += wrapper[i]; | |
return result; | |
} | |
private static int SumArrayWrapper2(ArrayWrapperNonInlined wrapper) | |
{ | |
int result = 0; | |
var count = wrapper.Count; | |
for (int i = 0; i < count; i++) | |
result += wrapper[i]; | |
return result; | |
} | |
private static int SumGeneric<TList>(TList wrapper) | |
where TList : IList<int> | |
{ | |
int result = 0; | |
var count = wrapper.Count; | |
for (int i = 0; i < count; i++) | |
result += wrapper[i]; | |
return result; | |
} | |
private struct ArrayWrapperNonInlined : IList<int> | |
{ | |
private readonly int[] _array; | |
public int Count | |
{ | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
get { return _array.Length; } | |
} | |
public ArrayWrapperNonInlined(int[] array) | |
{ | |
_array = array; | |
} | |
public int this[int index] | |
{ | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
get { return _array[index]; } | |
set { _array[index] = value; } | |
} | |
public IEnumerator<int> GetEnumerator() { throw new NotImplementedException(); } | |
IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } | |
public void Add(int item) { throw new NotImplementedException(); } | |
public void Clear() { throw new NotImplementedException(); } | |
public bool Contains(int item) { throw new NotImplementedException(); } | |
public void CopyTo(int[] array, int arrayIndex) { throw new NotImplementedException(); } | |
public bool Remove(int item) { throw new NotImplementedException(); } | |
public bool IsReadOnly => true; | |
public int IndexOf(int item) { throw new NotImplementedException(); } | |
public void Insert(int index, int item) { throw new NotImplementedException(); } | |
public void RemoveAt(int index) { throw new NotImplementedException(); } | |
} | |
private struct ArrayWrapper : IList<int> | |
{ | |
private readonly int[] _array; | |
public int Count => _array.Length; | |
public ArrayWrapper(int[] array) | |
{ | |
_array = array; | |
} | |
public int this[int index] | |
{ | |
get { return _array[index]; } | |
set { _array[index] = value; } | |
} | |
public IEnumerator<int> GetEnumerator() { throw new NotImplementedException(); } | |
IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } | |
public void Add(int item) { throw new NotImplementedException(); } | |
public void Clear() { throw new NotImplementedException(); } | |
public bool Contains(int item) { throw new NotImplementedException(); } | |
public void CopyTo(int[] array, int arrayIndex) { throw new NotImplementedException(); } | |
public bool Remove(int item) { throw new NotImplementedException(); } | |
public bool IsReadOnly => true; | |
public int IndexOf(int item) { throw new NotImplementedException(); } | |
public void Insert(int index, int item) { throw new NotImplementedException(); } | |
public void RemoveAt(int index) { throw new NotImplementedException(); } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment