Click here to Skip to main content
Click here to Skip to main content

Coding Tip for Performance Improvement .Net

By , 16 May 2010
Rate this:
Please Sign up or sign in to vote.
I always find this thing while doing code reviews and that is a performance issue. The above point I haven’t found anywhere as a performance issue, so I thought to share it.
 
Scenario: There is a function in which one need to extract 10-20 values from an object for example a column value from Dataset. Mostly it was written as:
 
String colValue = dataSet.Tables[0].Rows[0][0]
colValue = dataSet.Tables[0].Rows[0][1]
.
colValue = dataSet.Tables[0].Rows[0][20]
 
So what is wrong with the above code?
Let me ask you a question before I answer this – How does a CLR executes your c# code? Ahhhh… common you will say – the compiler converts it to Intermediate language and then CLR will execute it with JIT. Great you know it all, but do you check IL generated for you code?. (I’m not an exception here Wink | ;) )
 
Try it yourself – write the above code in an library and open it (dll) with ILDASM and navigate the function/method and double click it to see the IL code generated for that function.
 
All right I’ll suggest to write above code like this
 
DataRow dr = DataSet.Tables[0].Rows[0];
String colValue = dr[0]
colValue = dr[1]
.
.
colValue = dr[20]
 
Check the IL code generated for the following code. I’ve attached the c# code and its IL version:
 
public class ILExample
    {
        public void FillTableValuesA()
        {
            DataSet dataSet = new DataSet();
            dataSet.Tables.Add(new DataTable());
            String colValue = dataSet.Tables[0].Rows[0][1].ToString(); //There are 11 lines of IL for this single line
            colValue = dataSet.Tables[0].Rows[0][1].ToString();   //hence for 3 calls there are 33 lines
            colValue = dataSet.Tables[0].Rows[0][2].ToString();
        }
        public void FillTableValuesB()
        {
            DataSet dataSet = new DataSet();
            dataSet.Tables.Add(new DataTable());
            DataRow dr = dataSet.Tables[0].Rows[0]; //Here are few additional lines but worthy
            String colValue = dr[1].ToString();//There are 4 lines of IL for this single line
            colValue = dr[1].ToString();  //hence for 3 calls there are 12 lines
            colValue = dr[2].ToString();
        }
    }
The IL code for the above functions, I've added proper comments(green) to elaborate it:
.method public hidebysig instance void  FillTableValuesA() cil managed
{
  // Code size       130 (0x82)
  .maxstack  2
  .locals init ([0] class [System.Data]System.Data.DataSet dataSet,
           [1] string colValue)
  IL_0000:  nop
  IL_0001:  newobj     instance void [System.Data]System.Data.DataSet::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  callvirt   instance class [System.Data]System.Data.DataTableCollection [System.Data]System.Data.DataSet::get_Tables()
  IL_000d:  newobj     instance void [System.Data]System.Data.DataTable::.ctor()
  IL_0012:  callvirt   instance void [System.Data]System.Data.DataTableCollection::Add(class [System.Data]System.Data.DataTable)
  IL_0017:  nop
//This code is for String colValue = dataSet.Tables[0].Rows[0][1].ToString();
//First it loads DataSet Object
  IL_0018:  ldloc.0
// Call getTables() function to get .Tables collection
  IL_0019:  callvirt   instance class [System.Data]System.Data.DataTableCollection [System.Data]System.Data.DataSet::get_Tables()
  IL_001e:  ldc.i4.0
// Call get_Item() function to get 0th Table from Tables collection
  IL_001f:  callvirt   instance class [System.Data]System.Data.DataTable [System.Data]System.Data.DataTableCollection::get_Item(int32)
// Call get_Rows() function to get .Rows collection from 0th Table
  IL_0024:  callvirt   instance class [System.Data]System.Data.DataRowCollection [System.Data]System.Data.DataTable::get_Rows()
  IL_0029:  ldc.i4.0
// Call get_Item() function to get 0th Row from .Rows collection
  IL_002a:  callvirt   instance class [System.Data]System.Data.DataRow [System.Data]System.Data.DataRowCollection::get_Item(int32)
  IL_002f:  ldc.i4.1
// Call get_Item() function to get 1st column from 0th Row
  IL_0030:  callvirt   instance object [System.Data]System.Data.DataRow::get_Item(int32)
// Convert the column’s value to string
  IL_0035:  callvirt   instance string [mscorlib]System.Object::ToString()
// Store the current value on Stack (i.e. string value of the column) to 1st local variable 
//(i.e. colValue; check .locals init function at the beginning)
  IL_003a:  stloc.1
//Code ends here

//This code is for colValue = dataSet.Tables[0].Rows[0][1].ToString();
  IL_003b:  ldloc.0
  IL_003c:  callvirt   instance class [System.Data]System.Data.DataTableCollection [System.Data]System.Data.DataSet::get_Tables()
  IL_0041:  ldc.i4.0
  IL_0042:  callvirt   instance class [System.Data]System.Data.DataTable [System.Data]System.Data.DataTableCollection::get_Item(int32)
  IL_0047:  callvirt   instance class [System.Data]System.Data.DataRowCollection [System.Data]System.Data.DataTable::get_Rows()
  IL_004c:  ldc.i4.0
  IL_004d:  callvirt   instance class [System.Data]System.Data.DataRow [System.Data]System.Data.DataRowCollection::get_Item(int32)
  IL_0052:  ldc.i4.1
  IL_0053:  callvirt   instance object [System.Data]System.Data.DataRow::get_Item(int32)
  IL_0058:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_005d:  stloc.1
//Code ends here

//This code is for colValue = dataSet.Tables[0].Rows[0][2].ToString();
  IL_005e:  ldloc.0
  IL_005f:  callvirt   instance class [System.Data]System.Data.DataTableCollection [System.Data]System.Data.DataSet::get_Tables()
  IL_0064:  ldc.i4.0
  IL_0065:  callvirt   instance class [System.Data]System.Data.DataTable [System.Data]System.Data.DataTableCollection::get_Item(int32)
  IL_006a:  callvirt   instance class [System.Data]System.Data.DataRowCollection [System.Data]System.Data.DataTable::get_Rows()
  IL_006f:  ldc.i4.0
  IL_0070:  callvirt   instance class [System.Data]System.Data.DataRow [System.Data]System.Data.DataRowCollection::get_Item(int32)
  IL_0075:  ldc.i4.2
  IL_0076:  callvirt   instance object [System.Data]System.Data.DataRow::get_Item(int32)
  IL_007b:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_0080:  stloc.1
//Code ends here

  IL_0081:  ret
} // end of method ILExample::FillTableValuesA
//Function ends here
 
//Function FillTableValuesB starts here
.method public hidebysig instance void  FillTableValuesB() cil managed
{
  // Code size       88 (0x58)
  .maxstack  2
  .locals init ([0] class [System.Data]System.Data.DataSet dataSet,
           [1] class [System.Data]System.Data.DataRow dr,
           [2] string colValue)
  IL_0000:  nop
  IL_0001:  newobj     instance void [System.Data]System.Data.DataSet::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  callvirt   instance class [System.Data]System.Data.DataTableCollection [System.Data]System.Data.DataSet::get_Tables()
  IL_000d:  newobj     instance void [System.Data]System.Data.DataTable::.ctor()
  IL_0012:  callvirt   instance void [System.Data]System.Data.DataTableCollection::Add(class [System.Data]System.Data.DataTable)
  IL_0017:  nop
  IL_0018:  ldloc.0
  IL_0019:  callvirt   instance class [System.Data]System.Data.DataTableCollection [System.Data]System.Data.DataSet::get_Tables()
  IL_001e:  ldc.i4.0
  IL_001f:  callvirt   instance class [System.Data]System.Data.DataTable [System.Data]System.Data.DataTableCollection::get_Item(int32)
  IL_0024:  callvirt   instance class [System.Data]System.Data.DataRowCollection [System.Data]System.Data.DataTable::get_Rows()
  IL_0029:  ldc.i4.0
  IL_002a:  callvirt   instance class [System.Data]System.Data.DataRow [System.Data]System.Data.DataRowCollection::get_Item(int32)
  IL_002f:  stloc.1
//This code is for String colValue = dr[1].ToString();
// Load first local variable that is dr
  IL_0030:  ldloc.1
  IL_0031:  ldc.i4.1
// Get first column
  IL_0032:  callvirt   instance object [System.Data]System.Data.DataRow::get_Item(int32)
// Convert the column’s value to string
  IL_0037:  callvirt   instance string [mscorlib]System.Object::ToString()
// Store the current value on Stack (i.e. string value of the column) to 2nd local variable 
//(i.e. colValue; check .locals init function at the beginning)
  IL_003c:  stloc.2
//Code ends here

//This code is for colValue = dr[1].ToString();
  IL_003d:  ldloc.1
  IL_003e:  ldc.i4.1
  IL_003f:  callvirt   instance object [System.Data]System.Data.DataRow::get_Item(int32)
  IL_0044:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_0049:  stloc.2
//Code ends here

//This code is for colValue = dr[2].ToString();
  IL_004a:  ldloc.1
  IL_004b:  ldc.i4.2
  IL_004c:  callvirt   instance object [System.Data]System.Data.DataRow::get_Item(int32)
  IL_0051:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_0056:  stloc.2
//Code ends here

  IL_0057:  ret
} // end of method ILExample::FillTableValuesB
 
The collections make above code more expensive because to get one item it has to search whole collection(with indexes its easy though). And the second function makes the code more legible.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Hemant__Sharma
Technical Lead L & T Infotech
India India
No Biography provided

Comments and Discussions

 
QuestionCan you add a "real life" example with performance counters? PinmemberOshtri Deka21-May-12 21:49 
GeneralI am not sure about the performance yet, because you have in... Pinmemberzenwalker198512-Nov-11 16:30 
QuestionUnclear PinmemberPIEBALDconsult8-Dec-11 10:58 
AnswerRe: Unclear PinmemberOshtri Deka21-May-12 21:44 
GeneralInteresting Tip PinmemberJeremy Hutchinson20-May-10 10:09 
GeneralRe: Interesting Tip PinmemberHemant-Sharma-8127-May-10 1:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140421.2 | Last Updated 17 May 2010
Article Copyright 2010 by Hemant__Sharma
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid