.net - Why running generic aggregation method is many times slower? -
i'm having performance problem entity framework while using generic methods data aggregation. when querying max value of (indexed) id column of table few hundred thousands of rows using generic methods i'm getting huge performance drop. i'm using code-generated int keys instead of sql identities, code used next new id.
here's sample illustration. maxtyped
uses max
on db.posts
(which dbset<post>
), while maxgeneric
uses generic method max
same.
static int maxtyped() { using (var db = new bloggingcontext()) { return db.posts.max(p => p.postid); } } static int maxgeneric() { using (var db = new bloggingcontext()) { return max(db.posts, p => p.postid); } } static int max<t>(dbset<t> set, func<t, int> func) t : class { // intellisense says ienumerable.max return set.max(func); }
on not old home desktop quite fast hdd, maxtyped
on 100k rows runs in 0.5s, while maxgeneric
around 6.5s. 1 order of magnitude slower.
on office old testing server we're having times of few seconds vs 10 minutes.
the trace of problem i've found difference in intellisense's output max method in both cases: in maxtyped
identifies method iqueryable.max
, while in max used maxgeneric
says ienumerable.max
, might mean ef doing max on loaded entities , not in database. tried casting set
iqueryable<t>
, nothing changed. why there's such difference? how fix it?
because maxtyped
executed "server side", single row returned, while maxgeneric
executed "client side", rows of table returned, "deserialized" int
, "max(ed)" (this last step fastest one)
the real cost in passage of data between sql server , .net application: less data has passed, better it's.
now try
static int max<t>(dbset<t> set, expression<func<t, int>> func) t : class { // intellisense says ienumerable.max return set.max(func); }
and see if set.max
using ienumerable<t>.max()
or iqueriable<t>.max()
. if it's using second one, speed should around 0.5 secs.
the difference iqueriable<t>.max()
accepts expression<func<t, int>>
, while ienumerable<t>.max()
accepts func<t, int>
, , when write p => p.postid
can expression<func<>>
or func<>
depending on type of variable it's put in.
Comments
Post a Comment