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

In C#, custom string extensions methods are very powerful and popular feature, but when speed counts, they are not as quick as one would expect. They add overhead of roughly 1ms to the code call. Moreover, in below code speed checks, a by ref call is worse.  

The inline version string extension manipulation is very quick and very close to that of  the Path.GetExtension method.


Update 07/07/2020

This GetFileNameExtension string extension has been update, to work in all unit tests.





Source Code 
In case the above JIT compiler disappears


using System;
using System.IO; 
using System.Diagnostics; 

public static class StringExtension
{    
     /// <summary>
        /// Get filename extension, not ext of . only returns empty string, mirrors Path.GetExtension not try/catch issues by metadataconsulting.blogspot.com
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string GetFileNameExtension(this string s)
        {
            string ext = "";
            int fileExtPos = s.LastIndexOf('.');
            if (fileExtPos > s.LastIndexOf('\\'))
            {
                ext = s.Substring(fileExtPos, s.Length - fileExtPos);
                if (ext.Length <= 1) ext = "";
            }
            else
                ext = "";
            return ext;
        }
}
     
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()
 {
  
  //string file = @"c:\foo\bar.cat\cheese.exe.e.x";
  string file = "cheese.log.txt";
  Console.WriteLine("Inline String Manipulation"); 
  Stopwatch s = new Stopwatch();
  s.Start(); 
   string ext = ""; 
   int fileExtPos = file.LastIndexOf('.');
            if (fileExtPos > file.LastIndexOf('\\'))
            {
                ext = file.Substring(fileExtPos, file.Length - fileExtPos);
                if (ext.Length <= 1) ext = "";
            }
            else
                ext = "";
  s.Stop();
  Console.WriteLine(ext+ " in ticks "+ s.ElapsedTicks); 
  
  Console.WriteLine("Native Path.IO Get Extension"); 
  s.Reset();
  s.Start();   
   ext = Path.GetExtension(file); 
  s.Stop(); 
  Console.WriteLine(ext+ " in ticks "+ s.ElapsedTicks); 

  Console.WriteLine("String Extension call"); 
  s.Reset();
  s.Start();   
   ext = file.GetFileNameExtension();
  s.Stop(); 
  Console.WriteLine(ext+ " in ticks "+ s.ElapsedTicks); 

  Console.WriteLine("By Ref Method Call");   
  s.Reset();
  s.Start();   
   ext = GetFileExtStringRef(ref file);
  s.Stop(); 
  
  Console.WriteLine(ext+ " in ticks "+ s.ElapsedTicks); 
  
 }
}

Wednesday, February 14, 2018

C# .NET Use of Yield Return Out of the Dating Loop Example

Here's an exampled of using Yield Return out of a loop example combined with a loop example 

As dotNetPerls states about yield statement;
Yield return is similar to a return statement (which passes control flow to the calling method), followed by a "goto" to the yield statement in the next iteration of the foreach.


In case above service goes away.

using System;
using System.Collections.Generic;
//
//Borrow from https://www.dotnetperls.com/yield
//
public class Program
{
 public static IEnumerable<int> ComputePower(int number, int exponent)
    {
        //
        //Return the result with yield out of a loop. Func/Method does not stop on 'return'. Yield return, returns control to continue below.
        //
        yield return 0; 
  
        int exponentNum = 0;
        int numberResult = 1;
        //
        // Continue loop until the exponent count is reached.
        //
        while (exponentNum < exponent)
        {
            //
            // Multiply the result.
            //
            numberResult *= number;
            exponentNum++;
            //
            // Return the result with yield.
            //
            yield return numberResult;
        }
    }
 
 public static void Main()
 {
        //
        // Compute powers of two
        //
        int exponent = 0; //no access to interator
        foreach (int value in ComputePower(2, 17))
        {
            
        Console.WriteLine("2^" + (exponent++).ToString() +"="+ value);   
        }
        Console.WriteLine();
 }
}

Wednesday, February 7, 2018

How to fix GDrive Download File - Failed Network Error

Lately downloading a file in GDrive is resulting in "Network Error". And it's been around for a while. 

Solution 

So here's a quick fix, select your file, right-click and choose "Get shareable link" and paste using my post to downloading files directly in GDrive.




GDrive Download File - Failed Network Error

Thursday, February 1, 2018

C# .NET HTML Agility Pack - Get HTML Table Column Counts




How to count table columns and rows using HTML Agility Pack. 




Code in-case above JIT service fails.


 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
using System;
using HtmlAgilityPack;
using System.Xml;
using System.Collections.Generic;
using System.Linq;
     
public class Program
{
 public static void Main()
 {
    
  string html ="<table style='box-sizing: border-box; border-collapse: collapse; border-spacing: 0px; max-width: 100%; position: relative; table-layout: fixed; width: 2034px; z-index: 1; color: rgb(0, 0, 0); font-family: Lato, Roboto, Arial, Tahoma, sans-serif; font-size: 10px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; border-top: 0px none; margin-left: 0px; margin-right: 0px; margin-top: 0px; margin-bottom: 1.5em'> <caption style='box-sizing: border-box'>Most Popular Content Management Systems</caption> <thead style='box-sizing: border-box'> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> CMS</th> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> Usage *</th> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> Change Since Jan 1</th> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> Market Share *</th> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> Change Since Jan 1</th> </tr> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> Type</th> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> Percentage</th> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> Date</th> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> Percentage</th> <th style='box-sizing: border-box; font-weight: bold; text-align: left; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px; background: rgba(0 0 0.05)'> Change Since Jan 1</th> </tr> </thead> <tfoot style='box-sizing: border-box'> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> Totals</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 33.3%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'>&nbsp;</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 76%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'>&nbsp;</td> </tr> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <td colspan='5' style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> *&nbsp;<strong style='box-sizing: border-box; font-weight: bold'>Usage</strong>&nbsp;is percentage of surveyed websites that use the associated CMS.&nbsp;<strong style='box-sizing: border-box; font-weight: bold'>Market Share</strong>&nbsp;is the percentage of surveyed websites powered by a CMS that use the associated CMS. For example, 25.8% of all surveyed websites use WordPress, and WordPress commands 59.1% market share of the total CMS market.</td> </tr> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <td colspan='5' style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> The data in this table is provided courtesy of&nbsp;<a target='_blank' style='box-sizing: border-box; color: rgb(63, 136, 197); text-decoration: none; transition: all 0.2s ease-in-out; background:' href='http://w3techs.com/'>W3Techs</a>&nbsp;and was captured in February 2016. To learn more about this topic visit the&nbsp;<a target='_blank' style='box-sizing: border-box; color: rgb(63, 136, 197); text-decoration: none; transition: all 0.2s ease-in-out; background:' href='http://w3techs.com/technologies/overview/content_management/all'>overview of content management systems</a>&nbsp;from W3Techs.</td> </tr> </tfoot> <tbody style='box-sizing: border-box'> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> WordPress</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 25.8%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> +0.2%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 59.1%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> +0.3%</td> </tr> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> Joomla</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 2.8%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> No Change</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 6.4%</td> <td rowspan='4' style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> No Change</td> </tr> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> Drupal</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 2.2%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> +0.1%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 4.9%</td> </tr> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> Magento</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 1.3%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> +0.1%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 2.9%</td> </tr> <tr style='box-sizing: border-box; border-bottom: 1px solid rgb(240, 240, 240)'> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> Blogger</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 1.2%</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> No Change</td> <td style='box-sizing: border-box; font-family: inherit; font-size: inherit; vertical-align: middle; border-bottom: 0.05) solid rgba(0; padding: 12px'> 2.7%</td> </tr> </tbody> </table>";  
  
  HtmlDocument htmlDoc = new HtmlDocument();
  
  htmlDoc.LoadHtml(html);
  
  var table = htmlDoc.DocumentNode.SelectSingleNode("//table[1]"); //select first table
 
                int columnUpperBound = 0;
  HtmlNodeCollection rows = table.SelectNodes("//tr"); //select are rows in first table
  
  int colCnt = 0;
  int x=1;
                int y=1;  
  foreach (HtmlNode row in rows)
  {
   colCnt = 0;
  
   foreach (HtmlNode cell in row.ChildNodes) 
          if (cell.Name == "td")
   {
          colCnt++;
                               Console.WriteLine("  "+(y++).ToString()+ ". "+cell.OuterHtml); 
    
   }
     
   y=1; 
   Console.WriteLine("row "+(x++).ToString()+ ". Column count="+colCnt);
   columnUpperBound = Math.Max(colCnt, columnUpperBound);
            
  }
  
  Console.WriteLine("Final column Count="+columnUpperBound);
 }
}