Tuesday, February 20, 2018

Performance Comparison of Existence Test for a Large Set using Big One Line If vs Else Ifs vs Dictionary Vs Fall Through Case Statement

Below is C# (Sharp) code compares performance for element existence in a large non-sequential set (only 312 elements) using in variety of typical code structures which are;

  1. one line IF (with  ORs) 
  2. multi-line Else Ifs 
  3. Fall Through Case Statement 
  4. Dictionary with Initialization Time
  5. Dictionary Lookup on Key, no init time
  6. Dictionary Lookup on Value, no init time
The live C# Code example below check's if a character is a vowel from a set of 312 Unicode vowels extending to Latin-Supplement Unicode code point.

Note: Under the hood C# compiler creates a dictionary for 6 or more case statements
https://youtu.be/1lnwO63LhRI?t=871

The results are rather surprising!

Friday, February 16, 2018

C# .NET - How to get exact Command (CMD) Line Arguments as Entered by User - Verbatim Echo

So many wrong ways to do this, and they are litter all over Stack Overflow. 

Many solutions follow Microsoft's documentation of iterating over the arguments array and output it as an interpreted string format. This is not necessarily the format that was inputted by the user! 

This is how to get the exact command line arguments as entered by the user.


string AppCMDName = Environment.GetCommandLineArgs()[0]; 
//gets fully qualified application name with or without .exe specified  
//but does not get surrounding double quotes used to qualify the
//cmd line path that may contain spaces. Single quotes not allowed in a path.
string commandLine = Environment.CommandLine.Replace(AppCMDName, "").TrimEnd();
if (commandLine.StartsWith("\"\""))
    commandLine = commandLine.Substring(2, commandLine.Length - 2).TrimStart(); 
    //remove surrounding quotes if used to specify cmd


Typical iteration over args array example from https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/main-and-command-args/how-to-display-command-line-arguments


class CommandLine
{ 
    static void Main(string[] args)
    {
        // The Length property provides the number of array elements
        System.Console.WriteLine("parameter count = {0}", args.Length);

        for (int i = 0; i < args.Length; i++)
        {
            System.Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
        }
    }
}
/* Output (assumes 3 cmd line args): 
    parameter count = 3
    Arg[0] = [a]
    Arg[1] = [b]
    Arg[2] = [c]
*/

Thursday, February 15, 2018

C# .NET System.IO.Path.GetExtension vs StringExtension LastIndexOf Performance Comparison

Custom string extensions method calls are not as quick as you think. It is much slower in comparison to Path.GetExtension method.

I checked these numbers in a VS Project, and seems string extension call is 10 larger when compiled online than compiling the project on my desktop using .NET Framework 4.0 Client Profile? Download vs project solution here, and share your results (don't forget to state .NET  Framework and version you are using).




When the above JIT compiler disappears, this will remain.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using System;
using System.IO; 
using System.Diagnostics; 

public static class StringExtension
{    
 public static string GetFileExtString(this string file) {
  
  int fileExtPos = file.LastIndexOf('.');
  if (fileExtPos >  file.LastIndexOf('\\'))
   return file.Substring(fileExtPos, file.Length - fileExtPos);
  else
   return "";
 }
}
     
public class Program
{
 
 
 public static string GetFileExtStringRef(ref string file) {
  
  //string ext="";
  int fileExtPos = file.LastIndexOf('.');
  if (fileExtPos >  file.LastIndexOf('\\'))
   return file.Substring(fileExtPos, file.Length - fileExtPos);
  else
   return "";
  
  
 }
 
 public static void Main()
 {
  
  Stopwatch s = new Stopwatch();
  s.Start(); 
  
   //string file = @"c:\foo\bar.cat\cheese.exe.e.x";
      string file = "cheese.log.txt";
   string ext = ""; 
   int fileExtPos = file.LastIndexOf('.');
   int fileLastBackSlash = file.LastIndexOf('\\'); 
   if (fileExtPos > fileLastBackSlash)
    ext = file.Substring(fileExtPos, file.Length - fileExtPos);
   
  s.Stop();
  
  Console.WriteLine(ext+ " in ticks "+ s.ElapsedTicks); s.Reset();
  
  s.Start();   
   ext = Path.GetExtension(file); 
  s.Stop(); 
  
  Console.WriteLine(ext+ " in ticks "+ s.ElapsedTicks); s.Reset();
  
  s.Start();   
   ext = file.GetFileExtString();
  s.Stop(); 
  
  Console.WriteLine(ext+ " in ticks "+ s.ElapsedTicks); s.Reset();
    
  s.Start();   
   ext = GetFileExtStringRef(ref file);
  s.Stop(); 
  
  Console.WriteLine(ext+ " in ticks "+ s.ElapsedTicks); s.Reset();
  
 }
}