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

Coding Tip for Performance Improvement .Net

By , 16 May 2010
 
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 ;))
 
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
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionCan you add a "real life" example with performance counters?memberOshtri Deka21 May '12 - 21:49 
GeneralI am not sure about the performance yet, because you have in...memberzenwalker198512 Nov '11 - 16:30 
QuestionUnclearmemberPIEBALDconsult8 Dec '11 - 10:58 
AnswerRe: UnclearmemberOshtri Deka21 May '12 - 21:44 
GeneralInteresting TipmemberJeremy Hutchinson20 May '10 - 10:09 
GeneralRe: Interesting TipmemberHemant-Sharma-8127 May '10 - 1:08 

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130513.1 | Last Updated 17 May 2010
Article Copyright 2010 by Hemant__Sharma
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid