2012-09-21 1 views
3

EF4 (System.Data.Entities, Nuget 패키지 없음)를 사용하고 LINQ 쿼리에 대해 직접 컨텍스트에 맞는 프로젝트가 있습니다. 여러 사용자가 (VS 테스트 부하 테스트를 사용하여) 로그인하여로드 테스트를 할 때마다 끔찍한 성능을 얻고 CPU가 100 %로 촬영되고 VS.NET은 높은 .NET 잠금 경합 및 높은 가비지 수집에 대한 경고를 발생시킵니다.높은 잠금 경합과 EF4를 사용한 ToList()의 성능 저하

프로파일 링과 조정을 잘 수행하면 모든 것이 LINQ 쿼리 자체의 실행 (어느 정도 예상 됨)과 .ToList() 호출에 대한 엄청난 양의 경합 결과에 많은 장소.

누구에게 경험이 있습니까? 원인은 무엇이며 어떻게 해결할 수 있습니까? 어떤 이유로 ToList() 호출을 처리해야합니까?

업데이트 : 몇 사람이 더 자세한 정보를 요청했습니다. 문제의 코드는 다음과 같습니다 (출시 할 수없는 항목을 제거하기 위해 약간의 조정).

var query = 
      from f in context.fs 
      where f.usr.Any((u) => u.id == id) 
      select new 
      { 
       FS = f, 
       f.fList, 
       E = from e in f.fList select new { e.er }, 
       L = from l in f.fList select new { l.id } 
      }; 
    var res = query.ToList(); 

로드가 많은 경우 동일한 코드가 여러 스레드에서 실행됩니다 (프로파일 러에서 13이라고 말함). ToList() 호출은 절대적인 살인이며 거의 모든 지연을 설명합니다.

+0

검색어에 대한 추가 정보를 제공해 주시겠습니까? 얼마나 많은 로그인을하고 있습니까? –

+0

퍼포먼스 프로 파일러가 있습니까? 문제가되는 잠금이 무엇인지 정확하게 알려야합니다. 예를 들어'Expression' 클래스가 쿼리에 많이 사용되면 잠금 경합이 발생할 수 있기 때문에 EF 자체와 완전히 관련이 없습니다. 그 처리는 내부적으로 정적 필드에 대한 잠금을 사용하여 일부 캐시에 대한 액세스를 제어합니다. –

+0

.ToList() 호출의 코드와 호출 빈도 및 위치를 표시하는 것이 유용합니다. – Josh

답변

0

:

var query = from f in context.fs 
      where f.usr.Any((u) => u.id == id) 
      select new 
      { 
       FS = f, 
       f.fList 
      }; 
var res = query.ToList(); 
foreach (var x in res) 
{ 
    // runs in memory 
    var E = from e in x.fList select new e.er; 
    var L = from l in x.fList select new l.id; 
    // ... 
} 

만 E 필요 L은 그들을 결합하는 경우 :

을 당신은 전체 fList 개체가 쿼리를 실행 후 EL 에 투사를 수행해야하는 경우
var query = from f in context.fs 
      where f.usr.Any((u) => u.id == id) 
      select new 
      { 
       FS = f, 
       EL = from x in f.fList select new { e.er, l.id } 
      }; 
var res = query.ToList(); 
+0

매력처럼 작동했습니다! 감사!! – XeroxDucati

2

IQueryableIEnumerable 메서드가 다른 실행을 사용해야 함을 기억해야합니다. IQueryable 메서드는 일반적으로 메모리에서 표현 트리를 수정하는 것 이상을 수행하지 않습니다. 프로파일 러의 관점에서 보면 눈에 띄는 시간을 차지하지 않습니다. ToList 호출 (이전 IQueryable 메서드에서 생성 된 쿼리)이 실제로 실행되기 전까지는 실제 네트워크 IO가 발생하는 곳입니다. 시간을 보냈을 때 이 모두이 될 것입니다.

간단히 말해서 프로파일 러가 실제로 여기에서 도움이되지 않습니다. 모든 작업은 ToList으로 진행되지만 쿼리의 효율성을 결정하는 코드는 기본적으로 모든 곳에서 발생합니다. 원하는 것은 값 비싼 연산 일 수도 있고 쿼리를 효율적으로 작성하지 않은 것일 수도 있습니다.이 경우 정보를 제공하기 위해 더 많이 알 필요가 있습니다.

병렬 처리가 도움이되는지 여부는 실제로 알 수 없습니다. 아마도 내 생각 엔 그렇지 않을 것입니다. 귀하의 CPU가 최대가되면 바쁘게하고 스레딩은 더 많은 오버 헤드를 추가하고 속도를 저하시킵니다. CPU에 임무가 주어지지 않았지만 속도가 느린 경우 스레딩이 도움이 될 가능성이 큽니다. 쿼리에

+0

의미가 있습니다.하지만 EFprof는 쿼리가 반환하는 데 500ms 밖에 걸리지 않으며 거대한 데이터 세트가 아니라 소수의 필드 만이 아니라고 말합니다. 성능을 향상시키기 위해 모델을 조정할 방법이 있습니까? – XeroxDucati

+0

@ XeroxDucati 귀하가 이에 대한 충분한 정보를 포함하지 않았습니다. – Servy

+0

요청에 따라 코드가 추가되었습니다! – XeroxDucati