Thursday, December 20, 2012

Software architecture

Let me understand the real difference between "tire" and "layer" terms commonly used in architecture.

tire - referes to physical entity that is PC(s) and Server(s)
e.g - client machine running webbrowser, app serve running the web app, database server hosting the database. 

layer - refers to logical entity that is a component
e.g. userinterface layer, business logic layer, data access layer, database layer etc.

The conventiona asp or servlets, jsp or any web app that returns the html content and on the other side queries the database with SQL queries may not be a pure layered architecture because of the overlap of the layer reponsibilities.

A clean layered architecture could be

client - html, javascript, css client talking with a webservice using HTTP GET or POST, all presentation logic is part of javascript and css

dataaccess - webservice interfaceing with database using stored procedure (not SQL queries) to access data and return the data to the client in JSON or XML formats.

database - servers the webservice for the requested data using the stored procedures

The client machines can be many, the webservice if stateless can be
hosted in many servers for scalability reasons, the database server could be hosted in redudant high end server machines for availability reasons.

There are three logical "layers" and 3-tires but actually involving "n" number of physical machines.

client-HTTP(GET/POST)->webservice-TCP database connection ( to execute Stored Proc) ->DB
client<-http database="database" font="font" recordset-db="recordset-db" webservice="webservice">
 
No HTML is exchanged between client and webservice. 
No SQL command is issued by webservice to DB.

The above is a clean layered and tired architecture if the client, webservice and DB are deployed in different machines.

Reference: http://msdn.microsoft.com/en-us/library/aa905336.aspx

to be continued..

Wednesday, December 19, 2012

Auto Update

I am trying to understand how this software auto update might be working.
There could be three steps in it
1) Check for the availability of new version
2) Download the latest version
3) Install the downloaded version of software

Next i am going to expand on how each step could be designed or implemented

Check for availability of new version

When the current version of the application is started it could do the following in a background thread 1) Read the current version all the component that could be updated in the software
2) Go the vendor software update web server and check for the availability of newer version
2.1) Only if the exiting software license supports free updates
3) If newers version ar available the goto step2 or do nothing

Download the latest version

Options
1) Update the software user about the availability of newer version by displaying a message box and request the user for a manual update
2) Update the software user about the availability of newer version by dispaying a message box and request the user to intiate the auto download
2.1) Perform the download in the background (HTTP or FTP)

If download is successfully completed then goto to step 3 or display the error message to the user and the user to try again later.

Install the downloaded version of software

Note: Technology should support installation of newer version when current version of the software is running.
Install the downloaded software and request the user to restart the software.

Not sure how much of the above understanding and ideas are correct?

References
http://stackoverflow.com/questions/4499656/how-do-i-architect-automatic-update-of-my-clients


 

Thursday, August 30, 2012

Magic square!

Grid size:
 
What is row, column and diagonal?

diagonalcolumndiagonal
row
      
      
      
 
     

Magic square! is supported only on, Firefox 3 and above, Safari 3 and above, Google Chrome 3 and above and Internet Explorer 7 and above, web browsers.

Saturday, February 25, 2012

Scalability & Perfoamce

Load balance your website.
1) Use DNS (Domain Name Server) to distribute your website load.
2) Use Load Balancing Switch to distribute your website load.
The above mentioned load balancing methods work very well for static websites. But if your website have to do back end processing with a database or any other service, then even those services have to be load balanced otherwise they would become the bottle neck.

The above stuff is just the beginning of the vast topic called "Scalability"!
Abstraction interface
1) System abstraction interface help in hiding the complexity of the actual system and also the changes with in the system transparent to users of the system like hardware upgrade or adding hardware resource to scale up....
Scalability on the client

1) Paging concept (showing only few mail subjects on a mail client)

Scalability on the web/app server

1) multiple threads to handle http request
2) Load balancing architecture (one load balancing proxy server with multiple app server) to handle http request


External resources

Let's make the web faster
Web browser capabilities
Online web page testing
High Performance Web Sites and YSlow
Even Faster Websites
steve souders

to be continued.....

Android Findings

onConfigurationChanged - orientation change
Having "android:configChanges="orientation|keyboard" in manifest reloads the android activity on orientation change.
Instead the correct property is
"android:configChanges="orientation|keyboardHidden".

addJavascriptInterface - webview & javascript
When passing argument from javascript to android, pass it as string. Now if you want to convert the passed string to Integer or Long, the do not use Integer.getInteger instead use Integer.valueOf, that is, use valueOf.

Java Math.ceil with Integers
If your try to do some thing like
Integer a=1;
Integer b=5;
Integer c=0;
c=(int)Math.ceil(a/b);
You will get only 0;
Instead do something like
Integer a=1;
Integer b=5;
Integer c=0;
c=(int)Math.ceil((a * 1.0)/b);
So that you will get 1.

cursor.close() - Right place to close the sqlite cursor
Don't
if(cursor.getCount() > 0)
{
 cursor.close();
}
Do
if(cursor.getCount() > 0)
{

}
cursor.close();
Reference:https://groups.google.com/group/android-developers/browse_thread/thread/706258dfb7cbee1d

Tuesday, May 17, 2011

html input button issue

Try the below script and click on fun2 button. Button inside label tag have some problem, that is the second button invokes the onclick of the first button and then the second button.




Now remove the label (begin and end) tag and try the same code. Everything would work fine.


 

Tuesday, May 10, 2011

Simple javascript optimizations

Let us see some of the most simple javascript scripts optimizations which can make big difference,

Rule: Consider using local variable instead of global variable.

Rule: Avoid using eval() or function constructor.

Rule: Pass function, not string to setTimeout() and setInterval(). Passing stirng is same as calling eval().

Rule: Avoid using with().

For-in loop vs for loop

Slow:
function forinloop()
{
    var count=10000;
    var arr=new Array();
    for(var i=0;i<count;i++)
    {
        arr[i]=i;
    }
    var value=0;
    for(var index in arr)
    {
        value+=arr[index];
    }
}
Faster:
function forloop()
{
    var count=10000;
    var arr=new Array();
    for(var i=0;i<count;i++)
    {
        arr[i]=i;
    }
    var value=0;
    count= arr.length;
    for(var index=0;index<count;index++)
    {
        value+=arr[index];
    }
}

Rule: Avoid using for-in loop, instead use for() loop.

String concatenation vs array join

Slow:

function stringcat()
{
    var count=10000;
    var str="";
    for(var i=0;i<count;i++)
    {
        str+="first,";
    }
}
Faster:
function arrayjoin()
{
    var count=10000;
    var arr=new Array();
    for(var i=0;i<count;i++)
    {
        arr[i]="first";
    }
    var str=arr.join("");
}

Rule: Avoid string concatenation and use array join. The performance difference in significant only in IE 7.

Inbuilt functions vs primitive operations

Slow:

function mathmin()
{
    var count=10000;    
    for(var i=0;i<count;i++)
    {
        var a=10;
        var b=5;
        var min = Math.min(a, b);
    }
}
Faster:
function primitiveop()
{
    var count=10000;    
    for(var i=0;i<count;i++)
    {
        var a=10;
        var b=5;
        var min = a < b ? a : b;
    }
}

Rule: Avoid function calls, try to use primitive operations. The performance difference in significant only in IE 7.

External function vs inline function

Slow:

function minfunction(a,b)
{
    var min = a < b ? a : b;
    return min;
}
function externalfunction()
{
    var count=10000;
    for(var i=0;i<count;i++)
    {
        var a=10;
        var b=5;
        var min=minfunction(a,b);
    }
}
Faster:
function inlinefunction()
{
    var count=10000;
    for(var i=0;i<count;i++)
    {
        var a=10;
        var b=5;
        var min = a < b ? a : b;
    }
}

Rule: Avoid external function calls, try to use inline functions. The performance difference in significant only in IE 7.

Comments in the script

Slow:
function withcomments()
{
    var count=50000;    
    for(var i=0;i<count;i++)
    {
        /* dummy comments */
        /* dummy comments */
        var a=10;
        /* dummy comments */
        /* dummy comments */
        var b=5;
        /* dummy comments */
        /* dummy comments */
        var min = a < b ? a : b;
        /* dummy comments */
    }
}
Faster:
function withoutcomments()
{
    var count=50000;
    for(var i=0;i<count;i++)
    {
        var a=10;
        var b=5;
        var min = a < b ? a : b;
    }
}

Rule: Avoid comments in performance critical script. The performance difference in significant only in IE 7.

Try catch in performance critical functions

Slow:
function withtrycatch()
{
    var count=50000;
    for(var i=0;i<count;i++)
    {
        try
        {
            var num=parseInt("10");
        }
        catch(e)
        {
            //handle exception
        }
        finally
        {

        }
    }
}
Faster:
function withouttrycatch()
{
    var count=50000;
    for(var i=0;i<count;i++)
    {
       var num=parseInt("10");
    }
}

Rule: Avoid using try catch inside performance critical function.

Monday, April 25, 2011

Search Engine Optimization (SEO)

Developing a website or web application which can be indexed by search engine is very critical and it is called searching engine optimization of the website or web application.

Before starting the optimization let us look at some of the basic rules to be followed

Rule: Focus on the originality and quality of the content of your website.

Rule: Remember your ultimate consumers are your users, not search engines.

Rule: Original content is ranked high in the search result page.

Rule: Increasing the traffic to your website is more important than the rank of the page in the search result.

Rule: Perform any kind of optimization only to improve the user experience.

Below are some of the critical optimization rules

Rule: Use brief, but descriptive title in "title" (<title>Search engine optimization<title/>) tag. Choose a title that effectively communicates the topic of the page's content.

Rule: Create unique title for each page of the website.

Rule: Google search engine does not use keywords "meta" tag (<meta name="keywords" content="search engine optimization, indexing, optimization, rules" />) for indexing.

Rule: Provide crisp and clear description of the webpage in the description "meta" tag (<meta name="description" content="Critical rules for search engine optimization." />). Also provide unique description for each page of the website.

Rule: Use | (pipe) or - (hyphen) as separator and not _ (underscore) in "title" tag and description "meta" tag.

Rule: Provide URLs with readable text (e.g. http://codingrules.blogspot.com/2010/06/unit-testing.html) or keywords to access a webpage and not auto generated text or numbers (e.g. http://codingrules.blogspot.com/2010/06/20006.html).

Rule: Regularly check for broken links and remove the same.

Rule: Provide naturally flowing hierarchy for navigation and text for navigation. Avoid drop down menu, images or animation for navigation.

Rule: Provide site map for the user.

Rule: Submit your website's site map (xml format) with Google's webmaster tools for search engine to index your website. Generate XML site map for your website from http://www.xml-sitemaps.com/. Also Google's webmaster tools help webmasters better control how Google interacts with their websites and get useful information from Google about their site.

Rule: Provide custom 404 page, which can guide user back to a working page.

Rule: Write easy to read text content. Avoid images for textual content.

Rule: Try to use words and phrases on the webpage which the user would be looking for.

Rule: Use descriptive anchor text for links.

Rule: Format links to make it easy for users to distinguish between regular text and the anchor text of links.

Rule: Links on your page maybe internal—pointing to other pages on your site—or external—leading to content on other sites. In either of these cases provide descriptive anchor text for better user experience. Anchor text is the clickable text that users will see as a result of a link,
and is placed within the anchor tag <a href="..."></a>.

Rule: Do not design you entire webpage (or website) as image. Provide some text on the webpage which can be indexed by search engines.

Rule: Use descriptive name for images and not like "img1.png" or "pic.png".

Rule: Provide "alt" and "title" attribute text in the "img" tag (<img alt="" title="" src="" />).

Rule: Use "heading" tags (h1 to h6) to emphasize important text.

Rule: If the company name or the website name is embedded as image, then make sure the same is made available as text in the webpage (e.g. "title" tag or description "meta" tag etc).

Rule: For webpages with photo gallery, apart from providing image "alt" and "title" text, let the users to provide comments, which will increase the textual content of the webpage. But make sure to moderate the user comments.

Rule: User comments section can improve the textual content of the webpage. Moderate the user comments to avoid spam content.

Rule: Provide "Related links" section of links with in your website to increase the traffic to your website.

Rule: Provide complete address of your company on the website either on one of the webpage or on all the pages.

Rule: Use the company/product/service information, where ever applicable, instead of using we or our.

Rule: Use Google places, Videos, Images, Facebook, Twitter, etc for promoting your website.


Watch the below videos for more on SEO.



Thursday, February 3, 2011

parseint defect

When using parseInt() in javascript to convert or check "08" (e.g. parseInt("08")), then it would return 0. Instead use parseInt("08",10), i.e base 10 for converting or checking.

Sunday, January 30, 2011

HTML GET and POST

Let us quickly try to understand GET and POST request in HTML.
GET is used to request data from server and POST is used to submit data to server.

Let us create a simple HTML page called request.html as show below
<html>
    <head>
        <title>
            Request
        </title>
    </head>
    <body>
        <form method="GET" action="response.php">
            Enter the GET METHOD text:
            <input type="text" name="getinput" value="get value"/>
            <br/>
            Enter the POST METHOD text:
            <input type="text" name="postinput" value="post value"/>
            <br/>
            <input type="submit" value="Submit"/>
        </form>
    </body>
</html>
Save request.html file under apache\htdocs folder in c:\ if you have one.

Now create another file called response.php as show below
<?php
echo "GET:".$_GET["getinput"]; //GET
echo "<br/>";
echo "POST:".$_POST["postinput"]; //POST
?>
Save response.php file under apache\htdocs folder in c:\ if you have one.

If you notice the request.html source code the form tag's method attribute is set to GET.
Now open the request.html file using any of your web browser (e.g. http://localhost/request.html).
After the file opens in your web browser, hit the submit button.
Now you can notice the address bar URL had changed to
http://localhost/response.php?getinput=get+value&postinput=post+value
The above URL is also called Query String.
And the response would be
GET:get value
POST:
The above result is because we used GET method to QUERY/POST data to the server.

Now change the method attribute (form tag) value to POST in the request.html file and save the file.

Now again open the request.html file using any of your web browser (e.g. http://localhost/request.html).
After the file opens in your web browser, hit the submit button.
Now you can notice the address bar URL had changed to
http://localhost/response.php
And the response would be
GET:
POST:post value
The above result is because we used POST method to POST data to the server.

Take some time and try to understand the request.html and response.php file source code.
Please read more on Hypertext Transfer Protocol and Query string.

Thursday, January 20, 2011

JSON with special character text in PHP with MySQL

If you want to use JSON with special characters text to write to MySQL database or read from MySQL database using javascript and PHP, follow the below steps

To save/write JSON with special character text,
In Javascript
1) Do encodeURIComponent to the value to be submitted in javascript before POST

In PHP
1) Do stripslashes of the received POST data
2) Do mysql_real_escape_string before insert or update SQL statement

To pass back special character text via JSON from database,
In PHP
1) Do json_encode before creating JSON string (Note: Do not include " before and after the encoded json value.)

Monday, January 17, 2011

Online IDE

I was searching for an online cloud based IDE to store and edit my hobby projects on the net. Then i found CODERUN.

Few more IDEs,

1) https://bespin.mozillalabs.com/
2) http://kodingen.com/

Online bookmarks

I have been using two laptops for some time. I used to save URL bookmarks in both the laptops. Recently i started using my Nokia 5800 and an iPad for web browsing. I started storing bookmarks in my iPad as well. I found it very difficult to remember the bookmarks and respective devices.
To solve this problem i found a decent enouhg solutions at google bookmarks.
Now i am managing all my bookmarks at google bookmarks. Now i can access my bookmarks from any where and any device!

Friday, January 14, 2011

USB computer

Let me quickly tell you how to make a USB computer!

1) get one 8/16 GB USB drive.
2) download ubuntu from ubuntu desktop to your PC/laptop.
3) burn the ubuntu iso onto the USB drive as per the instruction given on ubuntu desktop using the universal USB Installer, but select the persistance option ( step 4 in the univsal USB installer ) of your desired memory size.
4) great! Now you have a ubuntu USB computer.
5) now shut down your PC/laptop with out removing the ubuntu USB driver.
6) start your PC/laptop press F12 and a change the boot sequence to boot OS from mounted ubuntu USB drive.
7) do your work with the ubuntu USB drive.
8) once your are done with your work, shut down your PC/laptop and remove the ubuntu USB driver.
9) now carry your ubuntu USB computer where ever you want and mount it on any PC/laptop and do your work!

Saturday, September 18, 2010

Simple javascript DHTML optimizations

Let us see some of the most simple javascript scripts optimizations with respect to DHTML which can make big difference,

Caching the DOM element

DIV1 element
DIV2 element
DIV3 element
Slow:
function nodomcache()
{
    var count=1000;
    for(var i=0;i<count;i++)
    {
        var value1=document.getElementById("div1").innerHTML;
        var value2=document.getElementById("div2").innerHTML;
        var value3=document.getElementById("div3").innerHTML;
    }
}
Faster:
function domcache()
{
    var count=1000;
    var ele1=document.getElementById("div1");
    var ele2=document.getElementById("div2");
    var ele3=document.getElementById("div3");
    for(var i=0;i<count;i++)
    {
        var value1=ele1.innerHTML;
        var value2=ele2.innerHTML;
        var value3=ele3.innerHTML;
    }
}

Rule: Cache the element for better performance. This caching is applicable for all types or variables.

Creating dynamic HTML (appendChild vs innerHTML)

Slow:
function appendchildhtml()
{
    var count=100;
    var tblele=document.createElement("table");
    var tblbodyele=document.createElement("tbody");
    for(var i=0;i<count;i++)
    {
        var trele= document.createElement("tr");
        var tdele1= document.createElement("td");
        tdele1.appendChild(document.createTextNode(i))
        trele.appendChild(tdele1);
        var tdele2= document.createElement("td");
        tdele2.appendChild(document.createTextNode(i))
        trele.appendChild(tdele2);
        tblbodyele.appendChild(trele);

    }
    tblele.appendChild(tblbodyele);
    document.getElementById("result1").appendChild(tblele);
}
Faster:
function innerhtml()
{
    var count=100;
    var strHTML="";
    strHTML+="<table>";
    for(var i=0;i<count;i++)
    {
        strHTML+="<tr>";
        strHTML+="<td>";
        strHTML+=i;
        strHTML+="</td>";
        strHTML+="<td>";
        strHTML+=i;
        strHTML+="</td>";
        strHTML+="</tr>";

    }
    strHTML+="</table>";
    document.getElementById("result2").innerHTML=strHTML;
}

Rule: Use innerHTML for dynamically adding html content.

Friday, September 17, 2010

Javascript measurement tools

There are two important factor which has to be measured to identify the improvement in the code
  • Time taken to complete some operation
  • Memory usage of the application
Below is the example code for measuring the time.
<html>
    <head>
        <title>Time measurement tool</title>
        <script>
        function measureTimeElapsed()
        {
            var divlogoutput;
            var starttime;
            var endtime;
            var timeelapsed;
            starttime=(new Date()).getTime();
            for(var i=0;i<10000;i++)
            {
                var temp=parseInt("10");
            }
            endtime=(new Date()).getTime();
            timeelapsed=endtime-starttime;
            divlogoutput=document.getElementById("logoutput");
            //append the timeelapsed
            divlogoutput.innerHTML="<b>TimeElapsed:"+
                timeelapsed+"(milliseconds)</b><br/>";
        }
        </script>
    </head>
    <body onload="measureTimeElapsed()">
        <div id="logoutput">
        </div>
    </body>
</html>
Output:
Chrome 6.0:TimeElapsed:1(milliseconds)
Safari 3.2:TimeElapsed:10(milliseconds)
IE 7.0:TimeElapsed:27(milliseconds)
Mozilla Firefox:3.0.3:1(milliseconds)

Note: Profiling tools can be used for the measuring execution time and memory leak.

Note: If you are testing with Google Chrome or Mozilla Firefox then try console.time(name); and console.timeEnd(name);. Please refer Console API

Thursday, September 16, 2010

C# XmlWriter vs XmlDocument vs StreamWriter

Use XmlWriter for creating xml document.The below example uses the following classes
  • Contact class is used for storing name and address
  • AddressBook is the colleciton of Contact class
The c# code example in this article will generate xml document as below, but with 10000 contacts elements.
<AddressBook>
  <Contact>
    <Name>Person1</Name>
    <Address1><![CDATA[Number101]]></Address1>
    <Address2><![CDATA[Address501]]></Address2>
    <Zip>50001</Zip>
    <Phone><![CDATA[999991]]></Phone>
 </Contact>
</AddressBook>
The example first creates and populates an AddressBook class with 10000 Contact objects and measures time taken to generate the xml file with 10000 contacts using using XmlDocument, XmlWriter and StreamWriter (usign StringBuilder).
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Diagnostics;
using System.Xml.Linq;
namespace XmlWrite
{
    class Contact
    {
        public string Name { get; set; }
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public int Zip { get; set; }
        public string Phone { get; set; }
        public Contact(string strName, string strAddress1, string strAddress2,
            int iZip,
            string strPhone)
        {
            Name = strName;
            Address1 = strAddress1;
            Address2 = strAddress2;
            Zip = iZip;
            Phone = strPhone;
        }
    }
    class AddressBook
    {
        private List<Contact> InnerList = null;
        public List<Contact> GetContacts()
        {
            return InnerList;
        }
        public AddressBook()
        {
            InnerList = new List<Contact>();
        }
        public void Add(Contact objContact)
        {
            InnerList.Add(objContact);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch objSW = null;
            XmlDocument objXmlDoc = null;
            XmlWriter objXmlWriter = null;
            XDocument objXDoc = null;
            StringBuilder objSB = null;
            StreamWriter objStreamWriter = null;
            AddressBook objAddrBook = null;
            int iCount = 10000;
            List<Contact> objContacts = null;

            //populate contacts in the addressbook object model
            objAddrBook = new AddressBook();
            objSW = new Stopwatch();
            for (int i = 0; i < iCount; i++)
            {
                Contact objContact = null;
                string strName = "Person" + (i + 1);
                string strAddress1 = "Number" + (i + 101);
                string strAddress2 = "Address" + (i + 501);
                int iZip = 50000 + (i + 1);
                string strPhone = "99999" + (i + 1);
                objContact = new Contact(strName, strAddress1, strAddress2, iZip,
                    strPhone);
                objAddrBook.Add(objContact);
            }
            //xml creation using XmlDocument
            objSW.Reset();
            objSW.Start();
            objXmlDoc = new XmlDocument();
            XmlElement objXmlAddrBook = objXmlDoc.CreateElement("AddressBook");
            objContacts = objAddrBook.GetContacts();
            for (int i = 0; i < objContacts.Count; i++)
            {
                XmlElement objXmlContact = objXmlDoc.CreateElement("Contact");
                XmlElement objXmlName = objXmlDoc.CreateElement("Name");
                objXmlName.InnerText = objContacts[i].Name;
                objXmlContact.AppendChild(objXmlName);
                XmlElement objXmlAddress1 = objXmlDoc.CreateElement("Address1");
                objXmlAddress1.AppendChild(
                    objXmlDoc.CreateCDataSection(objContacts[i].Address1));
                objXmlContact.AppendChild(objXmlAddress1);
                XmlElement objXmlAddress2 = objXmlDoc.CreateElement("Address2");
                objXmlAddress2.AppendChild(
                    objXmlDoc.CreateCDataSection(objContacts[i].Address2));
                objXmlContact.AppendChild(objXmlAddress2);
                XmlElement objXmlZip = objXmlDoc.CreateElement("Zip");
                objXmlZip.InnerText = objContacts[i].Zip.ToString();
                objXmlContact.AppendChild(objXmlZip);
                XmlElement objXmlPhone = objXmlDoc.CreateElement("Phone");
                objXmlPhone.AppendChild(
                    objXmlDoc.CreateCDataSection(objContacts[i].Phone));
                objXmlContact.AppendChild(objXmlPhone);
                objXmlAddrBook.AppendChild(objXmlContact);
            }
            objXmlDoc.AppendChild(objXmlAddrBook);
            objXmlDoc.Save("address_dom.xml");
            objSW.Stop();
            Console.WriteLine("XML file created using XmlDocument");
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objSW.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objSW.ElapsedMilliseconds);

            //xml creation using XmlWriter
            objSW.Reset();
            objSW.Start();
            XmlWriterSettings objSettings = new XmlWriterSettings();
            objSettings.Indent = true;
            using (objXmlWriter = XmlWriter.Create("address_xw.xml", objSettings))
            {
                objXmlWriter.WriteStartElement("AddressBook");
                objContacts = objAddrBook.GetContacts();
                for (int i = 0; i < objContacts.Count; i++)
                {
                    objXmlWriter.WriteStartElement("Contact");

                    objXmlWriter.WriteStartElement("Name");
                    objXmlWriter.WriteString(objContacts[i].Name);
                    objXmlWriter.WriteEndElement();
                    objXmlWriter.WriteStartElement("Address1");
                    objXmlWriter.WriteCData(objContacts[i].Address1);
                    objXmlWriter.WriteEndElement();
                    objXmlWriter.WriteStartElement("Address2");
                    objXmlWriter.WriteCData(objContacts[i].Address2);
                    objXmlWriter.WriteEndElement();
                    objXmlWriter.WriteStartElement("Zip");
                    objXmlWriter.WriteString(objContacts[i].Zip.ToString());
                    objXmlWriter.WriteEndElement();
                    objXmlWriter.WriteStartElement("Phone");
                    objXmlWriter.WriteCData(objContacts[i].Phone);
                    objXmlWriter.WriteEndElement();

                    objXmlWriter.WriteEndElement();
                }
                objXmlWriter.WriteEndElement();
            }
            objSW.Stop();
            Console.WriteLine("XML file created using XmlWriter");
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objSW.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objSW.ElapsedMilliseconds);
            //xml creation using StringBuilder
            objSW.Reset();
            objSW.Start();
            objSB = new StringBuilder();
            objSB.AppendLine("<AddressBook>");
            objContacts = objAddrBook.GetContacts();

            for (int i = 0; i < objContacts.Count; i++)
            {
                objSB.AppendLine("<Contact>");
                objSB.AppendLine("<Name>" + objContacts[i].Name + "</Name>");
                objSB.AppendLine(
                "<Address1><![CDATA[" + objContacts[i].Address1 + "]]></Address1>");
                objSB.AppendLine(
                "<Address2><![CDATA[" + objContacts[i].Address2 + "]]></Address2>");
                objSB.AppendLine("<Zip>" + objContacts[i].Zip + "</Zip>");
                objSB.AppendLine(
                "<Phone><![CDATA[" + objContacts[i].Phone + "]]></Phone>");
                objSB.AppendLine("</Contact>");
            }
            objSB.AppendLine("</AddressBook>");
            using (objStreamWriter = new StreamWriter("address_sb.xml", false))
            {
                objStreamWriter.Write(objSB.ToString());
            }
            objSW.Stop();
            Console.WriteLine("XML file created using StringBuilder");
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objSW.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objSW.ElapsedMilliseconds);

            //xml creation using XDocument (LINQ)
            objSW.Reset();
            objSW.Start();
            objContacts = objAddrBook.GetContacts();
            XElement[] arrXElem = new XElement[objContacts.Count];
            for (int i = 0; i < objContacts.Count; i++)
            {
                arrXElem[i] = new XElement("Contact",
                    new XElement("Name", objContacts[i].Name),
                    new XElement("Address1",
                    new XCData(objContacts[i].Address1)),
                    new XElement("Address2",
                    new XCData(objContacts[i].Address2)),
                    new XElement("Zip", objContacts[i].Zip),
                    new XElement("Phone", new XCData(objContacts[i].Phone)));
            }
            objXDoc = new XDocument(new XElement("AddressBook",arrXElem));
            objXDoc.Save("address_xdocument.xml");
            objSW.Stop();
            Console.WriteLine("XML file created using XDocument");
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objSW.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objSW.ElapsedMilliseconds);

            Console.ReadLine();

        }
    }
}
Output:
XML file created using XmlDocument
TimeElapsed (Stopwatch float):90.0323ms
TimeElapsed (Stopwatch rounded):90ms
XML file created using XmlWriter
TimeElapsed (Stopwatch float):36.2555ms
TimeElapsed (Stopwatch rounded):36ms
XML file created using StringBuilder
TimeElapsed (Stopwatch float):91.5911ms
TimeElapsed (Stopwatch rounded):91ms
XML file created using XDocument
TimeElapsed (Stopwatch float):71.3794ms
TimeElapsed (Stopwatch rounded):71ms

Note: The StringBuilder performance can be improved by specifying the required capacity when creating the StringBuilder object.

Note: XmlDocument can be considered, if forward and backward reference is unavoidable during the generation of xml document.

Rule: Use XmlWriter for generating or creating xml document.

C# Structure vs Class

Structure performs better than the reference type (Class) with respect to CPU usage and memory usage. Consider using structure over class,
  • If your application has to support data which does not require inheritance and interface
  • The data is in large number
  • The data is only of primitive data type like integer, byte, float, etc.
  • Probability a graphics application or application which deals with large data

Note: Structure with large number of members will degrade the performance when passed as parameter/argument to functions because the values of the entire structure is copied as parameter/argument to the function.

Below code measures the creation of 100000 objects of a class and also measures the time taken to search an object from the collection.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;
namespace ClassTimeElapsed
{
    class Brick
    {
        public int Id;
        public float X;
        public float Y;
        public float Width;
        public float Height;
        public Color Color;
    }
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch objStopwatch;
            Brick[] arrBrick;
            int iCount;
            iCount = 100000;

            objStopwatch = new Stopwatch();
            objStopwatch.Reset();
            objStopwatch.Start();
            arrBrick = new Brick[iCount];

            for (int i = 0; i < iCount; i++)
            {
                arrBrick[i] = new Brick();
            }
            int iConst = 15;
            for (int i = 0; i < iCount; i++)
            {
                arrBrick[i].Id = i + 1;
                arrBrick[i].X = i * iConst;
                arrBrick[i].Y = 0;
                arrBrick[i].Width = 10;
                arrBrick[i].Height = 10;
                arrBrick[i].Color = Color.Teal;
            }
            objStopwatch.Stop();
            Console.WriteLine(
                "Class time elapsed for allocation and population");
            //timeelapsed
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objStopwatch.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objStopwatch.ElapsedMilliseconds);
            int iSearchId = 99880;
            Brick objBrick = null;
            objStopwatch.Reset();
            objStopwatch.Start();
            for (int i = 0; i < arrBrick.Length; i++)
            {
                if (iSearchId == arrBrick[i].Id)
                {
                    objBrick = arrBrick[i];
                    break;
                }
            }
            objStopwatch.Stop();
            Console.WriteLine(
                "Class time elapsed for searching");
            //search result
            Console.WriteLine(
                "search result: Id:{0},X:{1},Y:{2},Width:{3},Height:{4},Color:{5}",
                objBrick.Id, objBrick.X, objBrick.Y, objBrick.Width, objBrick.Height,
                objBrick.Color);
            //timeelapsed
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objStopwatch.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objStopwatch.ElapsedMilliseconds);
            Console.ReadLine();
        }
    }
}
Output:
Class time elapsed for allocation and population
TimeElapsed (Stopwatch float):13.7327ms
TimeElapsed (Stopwatch rounded):13ms
Class time elapsed for searching
search result: Id:99880,X:1498185,Y:0,Width:10,Height:10,Color:Color [Teal]
TimeElapsed (Stopwatch float):1.3015ms
TimeElapsed (Stopwatch rounded):1ms
Below code measures the creation of 100000 objects of a struct and also measures the time taken to search an object from the collection.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;
namespace StructTimeElapsed
{
    struct Brick
    {
        public int Id;
        public float X;
        public float Y;
        public float Width;
        public float Height;
        public Color Color;
    }
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch objStopwatch;
            Brick[] arrBrick;
            int iCount;
            iCount = 100000;
            objStopwatch = new Stopwatch();
            objStopwatch.Reset();
            objStopwatch.Start();
            arrBrick = new Brick[iCount];
            int iConst = 15;
            for (int i = 0; i < iCount; i++)
            {
                arrBrick[i].Id = i + 1;
                arrBrick[i].X = i * iConst;
                arrBrick[i].Y = 0;
                arrBrick[i].Width = 10;
                arrBrick[i].Height = 10;
                arrBrick[i].Color = Color.Teal;

            }
            objStopwatch.Stop();
            Console.WriteLine(
                "Struct time elapsed for allocation and population");
            //timeelapsed
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objStopwatch.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objStopwatch.ElapsedMilliseconds);
            int iSearchId = 99880;
            Brick objBrick;
            objBrick.Id = 0;
            objBrick.X = 0;
            objBrick.Y = 0;
            objBrick.Width = 0;
            objBrick.Height = 0;
            objBrick.Color = Color.Transparent;
            objStopwatch.Reset();
            objStopwatch.Start();
            for (int i = 0; i < arrBrick.Length; i++)
            {
                if (iSearchId == arrBrick[i].Id)
                {
                    objBrick = arrBrick[i];
                    break;
                }
            }
            objStopwatch.Stop();
            Console.WriteLine(
                "Struct time elapsed for searching");
            //search result
            Console.WriteLine(
                "search result: Id:{0},X:{1},Y:{2},Width:{3},Height:{4},Color:{5}",
                objBrick.Id, objBrick.X, objBrick.Y, objBrick.Width, objBrick.Height,
                objBrick.Color);
            //timeelapsed
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objStopwatch.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objStopwatch.ElapsedMilliseconds);
            Console.ReadLine();
        }
    }
}
Output:
Struct time elapsed for allocation and population
TimeElapsed (Stopwatch float):3.0684ms
TimeElapsed (Stopwatch rounded):3ms
Struct time elapsed for searching
search result: Id:99880,X:1498185,Y:0,Width:10,Height:10,Color:Color [Teal]
TimeElapsed (Stopwatch float):1.0981ms
TimeElapsed (Stopwatch rounded):1ms
Below code measures the memory usage of creation of 100000 objects of a class.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;
namespace ClassMemoryUsage
{
    class Brick
    {
        public int Id;
        public float X;
        public float Y;
        public float Width;
        public float Height;
        public Color Color;
    }
    class Program
    {
        static void Main(string[] args)
        {
            long lngGCMemStart = 0;
            long lngGCMemEnd = 0;
            long lngProcessMemStart = 0;
            long lngProcessMemEnd = 0;
            Brick[] arrBrick;
            int iCount;
            iCount = 100000;
            Process objProcess = Process.GetCurrentProcess();
            //Measure starting point memory
            lngGCMemStart = System.GC.GetTotalMemory(true);
            lngProcessMemStart = objProcess.PrivateMemorySize64;
            arrBrick = new Brick[iCount];
            for (int i = 0; i < iCount; i++)
            {
                arrBrick[i] = new Brick();
            }
            //Measure memory after allocating
            lngGCMemEnd = System.GC.GetTotalMemory(true);
            lngProcessMemEnd = objProcess.PrivateMemorySize64;
            int iConst = 15;
            for (int i = 0; i < iCount; i++)
            {
                arrBrick[i].Id = i+1;
                arrBrick[i].X = i*iConst;
                arrBrick[i].Y = 0;
                arrBrick[i].Width = 10;
                arrBrick[i].Height = 10;
                arrBrick[i].Color = Color.Teal;
            }
            Console.WriteLine("Class memory usage.");
            //memoryusage difference
            Console.WriteLine("GC Memory Use:{0} (bytes)",
                lngGCMemEnd - lngGCMemStart);
            Console.WriteLine("Process Memory Use:{0} (bytes)",
                lngProcessMemEnd - lngProcessMemStart);
            Console.WriteLine("GC Memory Start:{0} (bytes)",
                lngGCMemStart.ToString());
            Console.WriteLine("Process Memory Start:{0} (bytes)",
                lngProcessMemStart.ToString());
            Console.WriteLine("GC Memory End:{0} (bytes)",
                lngGCMemEnd.ToString());
            Console.WriteLine("Process Memory End:{0} (bytes)",
                lngProcessMemEnd.ToString());
            Console.ReadLine();
        }
    }
}
Output:
Class memory usage.
GC Memory Use:4802368 (bytes)
Process Memory Use:0 (bytes)
GC Memory Start:130648 (bytes)
Process Memory Start:9232384 (bytes)
GC Memory End:4933016 (bytes)
Process Memory End:9232384 (bytes)
Below code measures the memory usage of creation of 100000 objects of a struct.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;

namespace StructMemoryUsage
{
    struct Brick
    {
        public int Id;
        public float X;
        public float Y;
        public float Width;
        public float Height;
        public Color Color;
    }

    class Program
    {
        static void Main(string[] args)
        {
            long lngGCMemStart = 0;
            long lngGCMemEnd = 0;
            long lngProcessMemStart = 0;
            long lngProcessMemEnd = 0;
            Brick[] arrBrick;
            int iCount;
            iCount = 100000;
            Process objProcess = Process.GetCurrentProcess();
            //Measure starting point memory
            lngGCMemStart = System.GC.GetTotalMemory(true);
            lngProcessMemStart = objProcess.PrivateMemorySize64;
            arrBrick = new Brick[iCount];
            //Measure memory after allocating
            lngGCMemEnd = System.GC.GetTotalMemory(true);
            lngProcessMemEnd = objProcess.PrivateMemorySize64;
            int iConst = 15;
            for (int i = 0; i < iCount; i++)
            {
                arrBrick[i].Id = i + 1;
                arrBrick[i].X = i * iConst;
                arrBrick[i].Y = 0;
                arrBrick[i].Width = 10;
                arrBrick[i].Height = 10;
                arrBrick[i].Color = Color.Teal;
            }
            Console.WriteLine("Struct memory usage.");
            //memoryusage difference
            Console.WriteLine("GC Memory Use:{0} (bytes)",
                lngGCMemEnd - lngGCMemStart);
            Console.WriteLine("Process Memory Use:{0} (bytes)",
                lngProcessMemEnd - lngProcessMemStart);
            Console.WriteLine("GC Memory Start:{0} (bytes)",
                lngGCMemStart.ToString());
            Console.WriteLine("Process Memory Start:{0} (bytes)",
                lngProcessMemStart.ToString());
            Console.WriteLine("GC Memory End:{0} (bytes)",
                lngGCMemEnd.ToString());
            Console.WriteLine("Process Memory End:{0} (bytes)",
                lngProcessMemEnd.ToString());
            Console.ReadLine();
        }
    }
}
Output:
Struct memory usage.
GC Memory Use:3602368 (bytes)
Process Memory Use:0 (bytes)
GC Memory Start:130656 (bytes)
Process Memory Start:9232384 (bytes)
GC Memory End:3733024 (bytes)
Process Memory End:9232384 (bytes)

Why? Structure is created in the stack.Structure is a value type.

Rule: Consider using structure for supporting large number of objects(data) in your application.

C# StringBuilder vs String Concatenation

Use StringBuilder for string concatenation. Concatenation of string using StringBuilder has better performance over string.
Below code measures the time taken to concatenate a string for 5000 iteration using “string” and “StringBuilder”.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace StringVsStringBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch objStopwatch = new Stopwatch();
            string strValue=string.Empty;
            StringBuilder objSBValue = new StringBuilder();
            int iCount = 5000;
            objStopwatch.Reset();
            objStopwatch.Start();
            for (int i = 0; i < iCount; i++)
            {
                strValue = strValue+"simpleValue"+i.ToString();
            }
            objStopwatch.Stop();
            Console.WriteLine("concatenation using String.");
            Console.WriteLine(
                "TimeElapsed (Stopwatch float):{0}ms",
                objStopwatch.Elapsed.TotalMilliseconds
                );
            Console.WriteLine(
                "TimeElapsed (Stopwatch rounded):{0}ms",
                objStopwatch.ElapsedMilliseconds
                );
            //Console.WriteLine(strValue);
            objStopwatch.Reset();
            objStopwatch.Start();
            for (int i = 0; i < iCount; i++)
            {
                objSBValue.Append("simpleValue" + i.ToString());
            }
            objStopwatch.Stop();
            Console.WriteLine(
                "concatenation using StringBuilder."
                );
            Console.WriteLine(
                "TimeElapsed (Stopwatch float):{0}ms",
                objStopwatch.Elapsed.TotalMilliseconds
                );
            Console.WriteLine(
                "TimeElapsed (Stopwatch rounded):{0}ms",
                objStopwatch.ElapsedMilliseconds
                );
            //Console.WriteLine(objSBValue);
            Console.ReadLine();
        }
    }
}
Output:
concatenation using String.
TimeElapsed (Stopwatch float):316.6526ms
TimeElapsed (Stopwatch rounded):316ms
concatenation using StringBuilder.
TimeElapsed (Stopwatch float):2.4933ms
TimeElapsed (Stopwatch rounded):2ms

Why? Any object stored in heap is immutable with respect to size allocation, and any change to the underlying size will require reallocation. If the string is modified (concatenating another string onto it, changing its value), then a new string is created and this can have negative performance implications. The StringBuilder gets around the reallocation problem by using internal buffers. But once the buffer fills up, the reallocation occurs. It is recommended to specify the initial capacity to minimize the reallocation problem.

Rule: Use StringBuilder instead of string for string concatenation operation.

C# XmlReader vs XDocument vs XmlDocument

Use Xmlreader for parse xml document.
Create an xml file as show below, but with 10000 contact elements called as “address_xw_n.xml” and make it available in D driver (d:\).
<AddressBook>
  <Contact>
    <Name>Person1</Name>
    <Address1><![CDATA[Number101]]></Address1>
    <Address2><![CDATA[Address501]]></Address2>
    <Zip>50001</Zip>
    <Phone><![CDATA[999991]]></Phone>
 </Contact>
</AddressBook>
The below code demonstrate the time take to parse the above created xml file using XmlDocument, XDocument and XmlReader.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Diagnostics;
using System.Xml.Linq;
namespace XmlParse
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch objSW = null;
            String strNormalFilePath;
            strNormalFilePath = @"d:\address_xw_n.xml";
            XmlDocument xmlNDoc;
            XmlReader xmlNReader = null;
            XDocument xNDoc=null;
            objSW = new Stopwatch();

            //xml parsing using XmlDocument - Normal format
            objSW.Reset();
            objSW.Start();
            xmlNDoc = new XmlDocument();
            xmlNDoc.Load(strNormalFilePath);
            XmlElement xmlDocNElem = xmlNDoc.DocumentElement;
            for (int i = 0; i < xmlDocNElem.ChildNodes.Count; i++)
            {
                XmlNode xmlNode = xmlDocNElem.ChildNodes[i];
                for (int j = 0; j < xmlNode.ChildNodes.Count; j++)
                {
                    string strName = xmlNode.ChildNodes[j].Name;
                    string strValue = xmlNode.ChildNodes[j].ChildNodes[0].Value;
                    //Console.WriteLine(strName + "-" + strValue);
                }
            }
            //xmlNDoc = null;
            objSW.Stop();
            Console.WriteLine("XML parsing using XmlDocument - Normal format");
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objSW.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objSW.ElapsedMilliseconds);

            //xml parsing using XDocument - Normal format
            objSW.Reset();
            objSW.Start();
            xNDoc = XDocument.Parse(xmlNDoc.OuterXml);
            foreach (XElement e in xNDoc.Root.Elements())
            {
                foreach (XElement c in e.Elements())
                {
                    string strName = c.Name.ToString();
                    string strValue = c.Value;
                    //Console.WriteLine(strName+"-"+strValue);
                }
            }
            xNDoc = null;
            objSW.Stop();
            Console.WriteLine("XML parsing using XDocument - Normal format");
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objSW.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objSW.ElapsedMilliseconds);

            //xml parsing using XmlReader - Normal format
            objSW.Reset();
            objSW.Start();
            using (xmlNReader = XmlReader.Create(strNormalFilePath))
            {
                while (xmlNReader.Read())
                {
                    switch (xmlNReader.NodeType)
                    {
                        case XmlNodeType.Element:
                            {
                                switch (xmlNReader.Name)
                                {
                                    case "Name":
                                    case "Zip":
                                        {
                                            string strName = xmlNReader.Name;
                                            xmlNReader.Read();
                                            string strValue = xmlNReader.Value;
                                            //Console.WriteLine(strName +
                                            //  "-" + strValue);
                                            break;
                                        }
                                    case "Address1":
                                    case "Address2":
                                    case "Phone":
                                        {
                                            string strName = xmlNReader.Name;
                                            xmlNReader.Read();
                                            string strValue = xmlNReader.Value;
                                            //Console.WriteLine(strName +
                                            //  "-" + strValue);
                                            break;
                                        }
                                }

                                break;
                            }
                    }
                }
            }

            objSW.Stop();
            Console.WriteLine("XML parsing using XmlReader - Normal format");
            Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
                objSW.Elapsed.TotalMilliseconds);
            Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
                objSW.ElapsedMilliseconds);
            Console.ReadLine();


        }
    }
}
Output:
XML parsing using XmlDocument - Normal format
TimeElapsed (Stopwatch float):5232.8249ms
TimeElapsed (Stopwatch rounded):5232ms
XML parsing using XDocument - Normal format
TimeElapsed (Stopwatch float):114.9677ms
TimeElapsed (Stopwatch rounded):114ms
XML parsing using XmlReader - Normal format
TimeElapsed (Stopwatch float):42.7921ms
TimeElapsed (Stopwatch rounded):42ms

Note: XmlDocument can be considered, if forward and backward reference is unavoidable during the parsing of xml document.

Rule: Use XmlReader for parsing xml document.