using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
class Program
{
static void Main()
{
Allocation();
Argument();
Return();
Load();
}
static void Allocation()
{
// Time allocating the object.
const int max = 1000000;
var a = new Tuple<string, string>(
"",
"");
var b = new KeyValuePair<string, string>(
"",
"");
var c = (
"",
"");
var s1 = Stopwatch.StartNew();
// Version 1: allocate Tuple.
for (var i = 0; i < max; i++)
{
var tuple = new Tuple<string, string>(
"cat",
"dog");
}
s1.Stop();
var s2 = Stopwatch.StartNew();
// Version 2: allocate KeyValuePair.
for (var i = 0; i < max; i++)
{
var pair = new KeyValuePair<string, string>(
"cat",
"dog");
}
s2.Stop();
var s3 = Stopwatch.StartNew();
// Version 3: allocate tuple literal.
for (var i = 0; i < max; i++)
{
var pair = (
"cat",
"dog");
}
s3.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / max) +
" allocation, Tuple");
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / max) +
" allocation, KeyValuePair");
Console.WriteLine(((double)(s3.Elapsed.TotalMilliseconds * 1000000) / max) +
" allocation, Tuple literal");
Console.WriteLine();
}
static void Argument()
{
// Time passing the object as an argument to a function.
const int max = 10000000;
var a = new Tuple<string, string>(
"",
"");
var b = new KeyValuePair<string, string>(
"",
"");
var c = (
"",
"");
X(a);
X(b);
X(c);
var s1 = Stopwatch.StartNew();
for (var i = 0; i < max; i++)
{
X(a);
}
s1.Stop();
var s2 = Stopwatch.StartNew();
for (var i = 0; i < max; i++)
{
X(b);
}
s2.Stop();
var s3 = Stopwatch.StartNew();
for (var i = 0; i < max; i++)
{
X(c);
}
s3.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / max) +
" argument, Tuple");
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / max) +
" argument, KeyValuePair");
Console.WriteLine(((double)(s3.Elapsed.TotalMilliseconds * 1000000) / max) +
" argument, Tuple literal");
Console.WriteLine();
}
static void Return()
{
// Time returning the object itself.
const int max = 10000000;
var a = new Tuple<string, string>(
"",
"");
var b = new KeyValuePair<string, string>(
"",
"");
var c = (
"",
"");
Y(a);
Y(b);
Y(c);
var s1 = Stopwatch.StartNew();
for (var i = 0; i < max; i++)
{
Y(a);
}
s1.Stop();
var s2 = Stopwatch.StartNew();
for (var i = 0; i < max; i++)
{
Y(b);
}
s2.Stop();
var s3 = Stopwatch.StartNew();
for (var i = 0; i < max; i++)
{
Y(c);
}
s3.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / max) +
" return, Tuple");
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / max) +
" return, KeyValuePair");
Console.WriteLine(((double)(s3.Elapsed.TotalMilliseconds * 1000000) / max) +
" return, Tuple literal");
Console.WriteLine();
}
static void Load()
{
// Time accessing an element.
const int max = 10000000;
var a = new Tuple<string, string>(
"cat",
"dog");
var b = new KeyValuePair<string, string>(
"cat",
"dog");
var c = (
"cat",
"dog");
var list1 = new List<Tuple<string, string>>();
list1.Add(a);
Z(list1);
var list2 = new List<KeyValuePair<string, string>>();
list2.Add(b);
Z(list2);
var list3 = new List<(string, string)>();
list3.Add(c);
Z(list3);
var s1 = Stopwatch.StartNew();
for (var i = 0; i < max; i++)
{
Z(list1);
}
s1.Stop();
var s2 = Stopwatch.StartNew();
for (var i = 0; i < max; i++)
{
Z(list2);
}
s2.Stop();
var s3 = Stopwatch.StartNew();
for (var i = 0; i < max; i++)
{
Z(list3);
}
s3.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / max) +
" load, Tuple");
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / max) +
" load, KeyValuePair");
Console.WriteLine(((double)(s3.Elapsed.TotalMilliseconds * 1000000) / max) +
" load, Tuple literal");
Console.WriteLine();
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void X(Tuple<string, string> a)
{
// This and following methods are used in the benchmarks.
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void X(KeyValuePair<string, string> a)
{
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void X((string, string) a)
{
}
[MethodImpl(MethodImplOptions.NoInlining)]
static Tuple<string, string> Y(Tuple<string, string> a)
{
return a;
}
[MethodImpl(MethodImplOptions.NoInlining)]
static KeyValuePair<string, string> Y(KeyValuePair<string, string> a)
{
return a;
}
[MethodImpl(MethodImplOptions.NoInlining)]
static (string, string) Y((string, string) a)
{
return a;
}
static char Z(List<Tuple<string, string>> list)
{
return list[0].Item1[0];
}
static char Z(List<KeyValuePair<string, string>> list)
{
return list[0].Key[0];
}
static char Z(List<(string, string)> list)
{
return list[0].Item1[0];
}
}
8.3944 allocation, Tuple
0.4949 allocation, KeyValuePair
0.3457 allocation, Tuple literal (FASTEST)
2.16168 argument, Tuple
2.17551 argument, KeyValuePair
2.17316 argument, Tuple literal
1.84421 return, Tuple (FASTEST)
5.42422 return, KeyValuePair
5.32932 return, Tuple literal
2.44545 load, Tuple
3.27982 load, KeyValuePair
2.56207 load, Tuple literal