2011-10-14 6 views
2

나는 내 코드에서 다소 어리석은 성능 문제에 직면했다. 작은 조사 후, 나는 내 일반적인 목록을 캐스팅하는 데 사용되는 AsQueryable 메서드가 코드를 최대 8000 번 느려지는 것을 발견했습니다. 그래서 질문은 무엇입니까? 내가 즉시 성능을 얻을 것이기 때문에 여기, 내가 알고있는 것처럼Linq에서 AsQueryable이 너무 느린 이유는 무엇입니까?

class Program 
{ 
    static void Main(string[] args) 
    { 
     var c = new ContainerTest(); 
     c.FillList(); 

     var s = Environment.TickCount; 
     for (int i = 0; i < 10000; ++i) 
     { 
      c.TestLinq(true); 
     } 
     var e = Environment.TickCount; 
     Console.WriteLine("TestLinq AsQueryable - {0}", e - s); 

     s = Environment.TickCount; 
     for (int i = 0; i < 10000; ++i) 
     { 
      c.TestLinq(false); 
     } 
     e = Environment.TickCount; 
     Console.WriteLine("TestLinq as List - {0}", e - s); 

     Console.WriteLine("Press enter to finish"); 
     Console.ReadLine(); 
    } 
} 

class ContainerTest 
{ 
    private readonly List<int> _list = new List<int>(); 
    private IQueryable<int> _q; 

    public void FillList() 
    { 
     _list.Clear(); 
     for (int i = 0; i < 10; ++i) 
     { 
      _list.Add(i); 
     } 
     _q = _list.AsQueryable(); 
    } 

    public Tuple<int, int> TestLinq(bool useAsQ) 
    { 
     var upperBorder = useAsQ ? _q.FirstOrDefault(i => i > 7) : _list.FirstOrDefault(i => i > 7); 
     var lowerBorder = useAsQ ? _q.TakeWhile(i => i < 7).LastOrDefault() : _list.TakeWhile(i => i < 7).LastOrDefault();    

     return new Tuple<int, int>(upperBorder, lowerBorder); 
    } 
} 

UPD가, 내가 (이 컨테이너의 상속의 라인에없는 경우) 가능한 한 많이 AsQueryable 방법을 피할 수있는 예이다 문제

"악의 세력이 높임을 때 어둠의 그 시간에 무어를 방지"

+0

두 테스트 모두 동일한 결과를주지 못한다는 것을 알고 있습니다. – Fredou

+0

감사합니다. 버그를 발견했습니다 :) –

+1

왜이 컬렉션에서 AsQueryable을 호출하고 있습니까? 이 용도로는 전혀 적합하지 않습니다. 나중에 LINQ 메서드를 사용하면 단순히 컬렉션이 아니라 데이터베이스 테이블과 같은 "쿼리 가능한"것들에 대해 다른 종류의 표현 트리를 작성하게 될 것입니다. –

답변

0

이상 사용 LINQ 목록이 너무

수동 impleme로 당신이 AsQueryable가 확장 방법의 완전히 다른 세트가있는 IQueryable를 반환하기 때문에 두 시험이 같은 결과를

+2

foreach를 통한 LINQ를 사용하여 성능 차이가 거의 없습니다. 그것은 8000 배의 차이가없는 곳입니다. (솔직히 말해서 2 배의 차이가 거의 없습니다) –

+0

@ kirk woll, 테스트 결과가 나오지 않고 동일한 구현을 사용하지 않습니다. – Fredou

+0

좋습니다, 리스트를 사용하여 한 번만 TestLinq 메소드를 시도하고 두 번째로리스트 을 사용하십시오. AsQuerable –

0

를 제공하지 않는다는 것을 알고

편집

LINQ

보다 ntation 항상 빨라집니다 List 같은 것을 의도 한 LINQ 표준 쿼리 연산자.

Queryable 컬렉션은 RDBMS 또는 이와 유사한의 백업 저장소를 의미하고, List<>.FirstOrDefault() 반대로 당신이 IQueryable.FirstOrDefault()를 호출 할 때 당신은 다른 더 복잡한 코드 식 트리를 구축하고있다.

관련 문제