using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace StructBenchmark
{
	class Program
	{
		static ExplicitStructure explicitMember;
		static AutoStructure autoMember;

		static void Main(string[] args)
		{
			Stopwatch stopWatch = new Stopwatch();
			ExplicitStructure explicitStructure = new ExplicitStructure();
			AutoStructure autoStructure = new AutoStructure();
			int int32 = 0;
			short int16 = 0;
			byte int8 = 0;

			Console.WriteLine("******** StructBenchmark v1.0");
#if DEBUG
			Console.WriteLine("Debug Build");
#else
			Console.WriteLine("Release Build");
#endif
			Console.WriteLine("Running with " + (Debugger.IsAttached ? "attached debugger" : "no debugger attached"));
			Console.WriteLine("CLR Version: " + Environment.Version.ToString());
			Console.WriteLine("Operating System: " + Environment.OSVersion.ToString());
			Console.WriteLine("Processor Count: " + Environment.ProcessorCount.ToString());

			Console.WriteLine("**** Local variable Tests");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				int32++;
			stopWatch.Stop();
			Console.WriteLine(" * Int32 variable increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				int16++;
			stopWatch.Stop();
			Console.WriteLine(" * Int16 variable increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				int8++;
			stopWatch.Stop();
			Console.WriteLine(" * UInt8 variable increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");


			Console.WriteLine("**** LayoutKind.Auto Tests (Local variable)");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				autoStructure.Int32++;
			stopWatch.Stop();
			Console.WriteLine(" * Int32 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				autoStructure.Int16++;
			stopWatch.Stop();
			Console.WriteLine(" * Int16 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				autoStructure.Int8++;
			stopWatch.Stop();
			Console.WriteLine(" * UInt8 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");


			Console.WriteLine("**** LayoutKind.Explicit Tests (Local variable)");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				explicitStructure.Int32++;
			stopWatch.Stop();
			Console.WriteLine(" * Int32 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				explicitStructure.Int16++;
			stopWatch.Stop();
			Console.WriteLine(" * Int16 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				explicitStructure.Int8++;
			stopWatch.Stop();
			Console.WriteLine(" * UInt8 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");


			Console.WriteLine("**** LayoutKind.Auto Tests (Member variable)");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				autoMember.Int32++;
			stopWatch.Stop();
			Console.WriteLine(" * Int32 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				autoMember.Int16++;
			stopWatch.Stop();
			Console.WriteLine(" * Int16 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				autoMember.Int8++;
			stopWatch.Stop();
			Console.WriteLine(" * UInt8 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");


			Console.WriteLine("**** LayoutKind.Explicit Tests (Member variable)");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				explicitMember.Int32++;
			stopWatch.Stop();
			Console.WriteLine(" * Int32 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				explicitMember.Int16++;
			stopWatch.Stop();
			Console.WriteLine(" * Int16 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");

			stopWatch.Reset();
			stopWatch.Start();
			for (int i = 0; i < 1000000000; i++)
				explicitMember.Int8++;
			stopWatch.Stop();
			Console.WriteLine(" * UInt8 field increments (1000000000): " + stopWatch.ElapsedMilliseconds.ToString() + "ms");
		}
	}
}
