Friday, October 30, 2020

C# .NET Validate Drive Letter with compiler optimization aggressive in-lining for large fall-through case statements

Here's a surprise,  range operator is beaten by a large set of serial cases statements! 




In the below code example which validates a drive letter,  by 

using System.Runtime.CompilerServices;

you can adorn the case-statement method to be compiled with  

[MethodImplAttribute(MethodImplOptions.AggressiveOptimization )] and/or

[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]

to surprising results.  I was surprised by v6. v5 and v6 win on alternative runs.

Full documentation here - https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.methodimploptions


Source Code

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
					
public static class Program
{
	 //Fri 30-Oct-20 2:17pm metadataconsulting.ca 
	 //https://metadataconsulting.blogspot.com/2020/10/C-NET-Validate-Drive-Letter-with-compiler-optimization-aggressive-in-lining-for-large-fall-through-case-statements.html
	 //-> this method does not exist on the interwebs, trivial?
	 //-> fun with compiler switches to optimize case statements 
	
	 public static bool isValidDriveLetter(this string drivewithcolon)
	 {
		 
		 if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
		 {
			 drivewithcolon = drivewithcolon.ToUpper();
			 // this is surprisingly faster than the equivalent if statement
			 switch (drivewithcolon[0])
			 {
				 case 'A':
				 case 'B':
				 case 'C':
				 case 'D':
				 case 'E':
				 case 'F':
				 case 'G':
				 case 'H':
				 case 'I':
				 case 'J':
				 case 'K':
				 case 'L':
				 case 'M':
				 case 'N':
				 case 'O':
				 case 'P':
				 case 'Q':
				 case 'R':
				 case 'S':
				 case 'T':
				 case 'U':
				 case 'V':
				 case 'W':
				 case 'X':
				 case 'Y':
				 case 'Z':
					 return true;
				 default:
					 return false;
			 }
		 }
		 else
			 return false; 

	 }
     //range operator	
	 public static bool isValidDriveLetterV2(this string drivewithcolon)
	 {
		 		 
		 if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
		 {
			 drivewithcolon = drivewithcolon.ToUpper();
			 if (drivewithcolon[0] >= 'A' && drivewithcolon[0] <= 'Z') 
			 	return true;
			 else 
				 return false; 
		 }
		 else
			 return false; 

	 }
	
	 [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
	 public static bool isValidDriveLetterV3(this string drivewithcolon)
	 {
		 
		 if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
		 {
			 drivewithcolon = drivewithcolon.ToUpper();
			 // this is surprisingly faster than the equivalent if statement
			 switch (drivewithcolon[0])
			 {
				 case 'A':
				 case 'B':
				 case 'C':
				 case 'D':
				 case 'E':
				 case 'F':
				 case 'G':
				 case 'H':
				 case 'I':
				 case 'J':
				 case 'K':
				 case 'L':
				 case 'M':
				 case 'N':
				 case 'O':
				 case 'P':
				 case 'Q':
				 case 'R':
				 case 'S':
				 case 'T':
				 case 'U':
				 case 'V':
				 case 'W':
				 case 'X':
				 case 'Y':
				 case 'Z':
					 return true;
				 default:
					 return false;
			 }
		 }
		 else
			 return false; 

	 }	
	
	 [MethodImplAttribute(MethodImplOptions.AggressiveOptimization)]
	 public static bool isValidDriveLetterV4(this string drivewithcolon)
	 {
		 
		 if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
		 {
			 drivewithcolon = drivewithcolon.ToUpper();
			 // this is surprisingly faster than the equivalent if statement
			 switch (drivewithcolon[0])
			 {
				 case 'A':
				 case 'B':
				 case 'C':
				 case 'D':
				 case 'E':
				 case 'F':
				 case 'G':
				 case 'H':
				 case 'I':
				 case 'J':
				 case 'K':
				 case 'L':
				 case 'M':
				 case 'N':
				 case 'O':
				 case 'P':
				 case 'Q':
				 case 'R':
				 case 'S':
				 case 'T':
				 case 'U':
				 case 'V':
				 case 'W':
				 case 'X':
				 case 'Y':
				 case 'Z':
					 return true;
				 default:
					 return false;
			 }
		 }
		 else
			 return false; 

	 }	
	
	
	 [MethodImplAttribute(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
	 public static bool isValidDriveLetterV5(this string drivewithcolon)
	 {
		 
		 if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
		 {
			 drivewithcolon = drivewithcolon.ToUpper();
			 // this is surprisingly faster than the equivalent if statement
			 switch (drivewithcolon[0])
			 {
				 case 'A':
				 case 'B':
				 case 'C':
				 case 'D':
				 case 'E':
				 case 'F':
				 case 'G':
				 case 'H':
				 case 'I':
				 case 'J':
				 case 'K':
				 case 'L':
				 case 'M':
				 case 'N':
				 case 'O':
				 case 'P':
				 case 'Q':
				 case 'R':
				 case 'S':
				 case 'T':
				 case 'U':
				 case 'V':
				 case 'W':
				 case 'X':
				 case 'Y':
				 case 'Z':
					 return true;
				 default:
					 return false;
			 }
		 }
		 else
			 return false; 

	 }	

	[MethodImplAttribute(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
	public static bool isValidDriveLetterV6(this string drivewithcolon)
	 {
		 if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
		 {
			 drivewithcolon = drivewithcolon.ToUpper();		 
			 if (drivewithcolon[0] >= 'A' && drivewithcolon[0] <= 'Z') 
			 	return true;
			 else 
				 return false; 
		 }
		 else
			 return false; 

	 }
 	
	public static void Main()
	{
	    bool v1,v2,v3,v4,v5,v6 = false;  

		Stopwatch sw = new Stopwatch(); 

		sw.Start();
		v1= "Z:".isValidDriveLetter(); 
		sw.Stop();
		Console.WriteLine("is Z: valid drive letter ?{0}, v1 in {1} ticks.",v1.ToString(), sw.ElapsedTicks);
		
		sw.Reset(); 
		sw.Start();
		v2= "Z:".isValidDriveLetterV2(); 
		sw.Stop();
		Console.WriteLine("is Z: valid drive letter ?{0}, v2 in {1} ticks.",v2.ToString(), sw.ElapsedTicks);
	
	    sw.Reset(); 
		sw.Start();
		v3= "Z:".isValidDriveLetterV3(); 
		sw.Stop();
		Console.WriteLine("is Z: valid drive letter ?{0}, v3 in {1} ticks.",v3.ToString(), sw.ElapsedTicks);
	
	    sw.Reset(); 
		sw.Start();
		v4= "Z:".isValidDriveLetterV4(); 
		sw.Stop();
		Console.WriteLine("is Z: valid drive letter ?{0}, v4 in {1} ticks.",v4.ToString(), sw.ElapsedTicks);
	
		sw.Reset(); 
		sw.Start();
		v5= "Z:".isValidDriveLetterV5(); 
		sw.Stop();
		Console.WriteLine("is Z: valid drive letter ?{0}, v5 in {1} ticks.",v5.ToString(), sw.ElapsedTicks);
	
		sw.Reset(); 
		sw.Start();
		v6= "Z:".isValidDriveLetterV6(); 
		sw.Stop();
		Console.WriteLine("is Z: valid drive letter ?{0}, v6 in {1} ticks.",v6.ToString(), sw.ElapsedTicks);
		
		
	}
}

No comments:

Post a Comment