enterprise library - Why is reading a Dapper IEnumerable(dynamic) an order of magnitude slower than reading an IEnumerable(IDataRecord)? -


in comparing dapper enterprise library data access access block getting data via stored procedure. see overall performance benefit of 40% when using dapper, surprising.

however, when comparing iteration , getting data ienumerable(idatarecord) vs. ienumerable(dynamic), ienumerable(idatarecord) approximately order of magnitude faster. behavior understood , expected or there not right here?

the results:

ienumerable(idatarecord) enter image description here

ienumerable(dynamic) - using dapperobject.propertyname enter image description here

now interesting part, when using dapperobject["propertyname"], performance on par idatarecord. not @ have expected. enter image description here

the relevant portion of profiling code

using system; using system.collections.generic; using system.linq; using dapper.dataaccess; using system.data; using tophat;  namespace dapper.testrunner {     class program     {         static void main(string[] args)         {             var connectionstring = "data source=webdbdev3,1866; user id=hsbmhw;password=gener4y&m;persist security info='true'; initial catalog=myhomeworks;";             //the following uses tophat create singleton connection instance.             database.install<sqlserverconnectionfactory>(connectionstring, connectionscope.byrequest);             dappertest();             dappertest2();             enterpriselibraryidatarecordtest();          }          private static void dappertest()         {             (int = 0; < 100; i++)             {                 ienumerable<dynamic> users = myrepository.getusersdapper();                 populatebusinessobjectsdynamic(users);             }         }          private static void dappertest2()         {             (int = 0; < 100; i++)             {                 ienumerable<dynamic> users = myrepository.getusersdapper();                 populatebusinessobjectsdynamic2(users);             }         }          private static void enterpriselibraryidatarecordtest()         {             (int = 0; < 100; i++)             {                 ienumerable<idatarecord> users = myrepository.getusersentlib();                 populatebusinessobjectsidatarecord(users);             }         }          private static void populatebusinessobjectsdynamic(ienumerable<dynamic> users)         {             foreach (var user in users)             {                 businessobject bo = new businessobject(user);             }         }          private static void populatebusinessobjectsdynamic2(ienumerable<dynamic> users)         {             foreach (var user in users)             {                 businessobject bo = new businessobject(user);             }         }           private static void populatebusinessobjectsidatarecord(ienumerable<idatarecord> users)         {             foreach (var user in users)             {                 businessobject bo = new businessobject(user);             }         }     }        public class businessobject     {          public datetime createdate { get; set; }         public string createdatestring { get; set; }         public string firstname { get; set; }         public bool isapproved { get; set; }         public bool islockedout { get; set; }         public datetime lastactivitydate { get; set; }         public datetime lastlogindate { get; set; }         public string lastname {get;set;}         public string organization{get;set;}         public int organizationid{get;set;}         public int personid{get;set;}         public string profilelastupdatedby{get;set;}         public datetime profilelastupdateddate{get;set;}         public string rolename{get;set;}         public long rownumber{get;set;}         public int totalcount{get;set;}         public guid userid{get;set;}         public string username {get;set;}         public string userstatus{get;set;}          public businessobject(dynamic user)         {             createdate=user.createdate;             createdatestring = user.createdatestring;             firstname = user.firstname;             isapproved = user.isapproved;             islockedout = user.islockedout;             lastactivitydate= user.lastactivitydate;             lastlogindate = user.lastlogindate;             lastname = user.lastname;             organization = user.organization;             organizationid=user.organization_id;             personid = user.party_id;             profilelastupdatedby = user.profilelastupdatedby;             profilelastupdateddate = user.profilelastupdateddate;             rolename = user.rolename;             rownumber = user.rownumber;             totalcount = user.totalcount;             userid = user.userid;             username= user.username;             userstatus = user.userstatus;         }          public businessobject(bool x, dynamic user)         {             createdate = user["createdate"];             createdatestring = user["createdatestring"];             firstname = user["firstname"];             isapproved = user["isapproved"];             islockedout = user["islockedout"];             lastactivitydate = user["lastactivitydate"];             lastlogindate = user["lastlogindate"];             lastname = user["lastname"];             organization = user["organization"];             organizationid = user["organization_id"];             personid = user["party_id"];             profilelastupdatedby = user["profilelastupdatedby"];             profilelastupdateddate = user["profilelastupdateddate"];             rolename = user["rolename"];             rownumber = user["rownumber"];             totalcount = user["totalcount"];             userid = user["userid"];             username = user["username"];             userstatus = user["userstatus"];         }          public businessobject(idatarecord user)         {             createdate = (datetime)user["createdate"];             createdatestring = (string)user["createdatestring"];             firstname = (string)user["firstname"];             isapproved = (bool)user["isapproved"];             islockedout = (bool)user["islockedout"];             lastactivitydate = (datetime)user["lastactivitydate"];             lastlogindate = (datetime)user["lastlogindate"];             lastname = (string)user["lastname"];             organization = (string)user["organization"];             organizationid = (int)user["organization_id"];             personid = (int)user["party_id"];             profilelastupdatedby = (string)user["profilelastupdatedby"];             profilelastupdateddate = (datetime)user["profilelastupdateddate"];             rolename = (string)user["rolename"];             rownumber = (long)user["rownumber"];             totalcount = (int)user["totalcount"];             userid = (guid)user["userid"];             username = (string)user["username"];             userstatus = (string)user["userstatus"];         }     } } 

you seem running same test twice; input (users) same, here:

    private static void dappertest()     {         (int = 0; < 100; i++)         {             ienumerable<dynamic> users = myrepository.getusersdapper();             populatebusinessobjectsdynamic(users);         }     }      private static void dappertest2()     {         (int = 0; < 100; i++)         {             ienumerable<dynamic> users = myrepository.getusersdapper();             populatebusinessobjectsdynamic2(users);         }     } 

and actual "what do" same, here:

    private static void populatebusinessobjectsdynamic(ienumerable<dynamic> users)     {         foreach (var user in users)         {             businessobject bo = new businessobject(user);         }     }      private static void populatebusinessobjectsdynamic2(ienumerable<dynamic> users)     {         foreach (var user in users)         {             businessobject bo = new businessobject(user);         }     } 

so... have conclude "a combination of jit, data caching (at database server) assembly loading/validation/fusion, connection pooling, , dynamic cache features made second test appear faster".

note dynamic side of dapper intended ad-hoc usage anyway. if wanted optimal face of dapper, use query<t>, not dynamic.

in particular, afaik no build of dapper supports string indexer on dynamic api. object implements idictionary<string,object> member access, need explicitly cast use - can't user["propname"] if user typed dynamic (if i'm wrong, please tell me!).

as happens, unreleased "git" code (for dynamic api) noticeably faster current "nuget" implementation - bit of tangent specific question.


Comments

Popular posts from this blog

blackberry 10 - how to add multiple markers on the google map just by url? -

php - guestbook returning database data to flash -

delphi - Dynamic file type icon -