.net - Extension methods on IEnumerable<T>: how is it performance? -
from mentor: prefer native methods (implemented directly on collection) on extension methods of ienumerable, because:
the linq-to-objects extension methods implemented on ienumerable, meaning in worst-case scenario (when item search not exist in collection) have enumerate thru elements. if have contains or exists method implemented directly on collection, make use of internal knowledge , maybe hash table or other quick operation.
i confused, because think microsoft should have implemented hash table ienumerable contains/exists already. quick benchmark list , ienumerable show no differences:
static void main(string[] args) { console.write("input number of elements: "); int count = convert.toint32(console.readline()); console.write("input number of loops: "); int loop = convert.toint32(console.readline()); random r = new random(); stopwatch sw = new stopwatch(); (int = 0; < loop; i++) { var list = createlistofint(count); sw.start(); (int j = 0; j < count; j++) { docontains(list, r.next()); } sw.stop(); } console.writeline("list<t> native method: iterated {0} times on {1} elements, elapsed :{2}",loop,count,sw.elapsed); sw.reset(); (int = 0; < loop; i++) { var list = createlistofint(count); sw.start(); (int j = 0; j < count; j++) { docontainsenumerable(list, r.next()); } sw.stop(); } console.writeline("ienumerable<t> extension method: iterated {0} times on {1} elements, elapsed :{2}", loop, count, sw.elapsed); sw.reset(); (int = 0; < loop; i++) { var list = createlistofint2(count); sw.start(); (int j = 0; j < count; j++) { //make sure element not in list docontains(list, r.next(20000, 50000)); } sw.stop(); } console.writeline("list<t> native method: element not exist:iterated {0} times on {1} elements, elapsed :{2}", loop, count, sw.elapsed); sw.reset(); (int = 0; < loop; i++) { var list = createlistofint2(count); sw.start(); (int j = 0; j < count; j++) { //make sure element not in list docontainsenumerable(list, r.next(20000, 50000)); } sw.stop(); } console.writeline("ienumerable<t> extension method: element not exist: iterated {0} times on {1} elements, elapsed :{2}", loop, count, sw.elapsed); console.readkey(); } static list<int> createlistofint(int count) { random r = new random(1000); list<int> numbers = new list<int>(count); (int = 0; < count; i++) { numbers.add(r.next()); } return numbers; } static bool docontains(list<int> list, int number) { return list.contains(number); } static bool docontainsenumerable(ienumerable<int> list, int number) { return list.contains(number); } //define scope of randomly created number, make sure lookup number not in list static list<int> createlistofint2(int count) { random r = new random(1000); list<int> numbers = new list<int>(count); (int = 0; < count; i++) { numbers.add(r.next(0,10000)); } return numbers; }
}
edit: tried hashset implementation, increases performance:
sw.reset(); (int = 0; < loop; i++) { var list = createlistofint2(count); hashset<int> hashtable = new hashset<int>(list); sw.start(); (int j = 0; j < count; j++) { //make sure element not in list hashtable.contains(r.next(20000, 50000)); } sw.stop(); } console.writeline("ienumerable<t> extension method: element not exist: iterated {0} times on {1} elements, elapsed :{2}", loop, count, sw.elapsed);
still, opinion mentor saying?
can clear out me? mentor right? if he's right, wrong code?
thank
list<t>
contains
calls iterating list, won't faster extension method. if use hashset<t>
, try series of contains()
operations, find marked improvement.
edit: reason microsoft didn't utilize hash ienumerable<t>
extension methods not guarantee implementing class used hash or similar. had go naive approach because ienumerable<t>
interface guarantees implementing class enumerated.
Comments
Post a Comment