2014-05-20 4 views
3

다음 코드를 실행하는 데 시간이 오래 걸립니다. 성능을 향상시키기 위해 LINQ 또는 다른 방법으로 코드 아래를 대체 할 수있는 대안이 있습니까?중첩 된 foreach를 성능 향상으로 바꾸십시오.

var usedLists = new HashSet<long>(); 

foreach (var test in Tests) 
{ 
    var requiredLists = this.GetLists(test.test, selectedTag); 

    foreach (var List in requiredLists) 
    { 
     if (!usedLists.Contains(List.Id)) 
     { 
      usedLists.Add(List.Id); 
      var toRecipients = List.RecepientsTo; 
      var ccRecipients = List.RecipientsCC; 
      var bccRecipients = List.RecipientsBCC; 
      var replyTo = new List<string>() { List.ReplyTo }; 
      var mailMode = isPreviewMode ? MailMode.Display : MailMode.Drafts; 
      OutlookModel.Instance.CreateEmail(toRecipients, ccRecipients, bccRecipients, this.Draft, mailMode, replyTo); 
     } 
    } 
} 
+11

필자는 linq을 사용하면 더 빨리 처리 할 수 ​​있을지 의심 스럽다. 그리고 나는'CreateEmail' 함수가 항상 사용되는 것으로 생각한다. 코드를 프로파일 링하고 실제 병목 현상이 어디인지 확인하십시오. http://stackoverflow.com/questions/3927/what-are-some-good-net-profilers – Stormenet

+0

아니, 기본적으로 최선이 될 수 있습니다. – TheGeekZn

+0

'this.GetLists' 메소드는 어떻습니까? 이 두 가지 방법을 제외하고는이 코드에서 그다지 소모하지 않을 것이 없습니다. 또는 그룹화 된 메일을 한 번에 보낼 수도 있습니다 (동일한 초안을 항상 보냈기 때문에)해야 할 일에 반대하지 않는 경우 한 번에 보낼 수 있습니다. – mmg666

답변

1

실제로 무엇을하고 있습니까?

foreach (var test in Tests) 
{ 
    var requiredLists = this.GetLists(test.test, selectedTag); 
    foreach (var List in requiredLists) 
    { 
     if (!usedLists.Contains(List.Id)) 

을 보면 당신이 (모든 사람 "VAR"내가 말할 수있는 실제 유형) 독특한 "목록"의를 얻으려고 나에게 보인다. 그래서 당신은 실제로 (당신에 의해 기록 될) 새로운 기능이를 교체 할

var uniqueLists = this.GetUniqueLists(Tests, selectedTag); 

을 마지막으로 그 목록을 통해 반복하고 메일을 보낼 것

this.Sendmails(uniqueLists); 

를 호출 할 수 있습니다.

코드 속도를 높이거나 줄일 수있는 경우 기본 GetLists/GetUniqueLists 함수에 크게 의존합니다.

그러나 어떤 경우이든 코드를 크게 향상시킬 수 있습니다. 코드는 읽기 쉽고 테스트 할 수있게됩니다.

1

BackgroundWorker class 또는 비슷한 것으로 수행 할 수 있습니다. 아주 대략적인 개요는 전자 메일 인수를 별도의 클래스로 래핑 한 다음 루프가 목록 처리를 계속하는 동안 비동기 적으로 백그라운드 작업을 시작하는 것입니다.

Task class도 사용할 수 있습니다. 이것은 CreateEmail 함수가 항상 사용하는 함수라고 가정합니다. 항상 루프를 따라 가면서이 길을가는 것은 의미가 없습니다. 알고리즘의 복잡성을 보면 편집

는 GetLists()는 O (n)이 시간에 실행 호출하지만 CreateEmail는() O 그렇게 (N^2) 시간, 실행 호출 - 다른 모든 조건이 동일 - CreateEmail() 호출을 포함하는 코드 블록이 먼저 최적화하는 것이 더 좋습니다.

0
  • 각 foreach 루프는 루프가-그것을 조금 속도를 높일 수 있으므로 정기적를 사용하여 열거 자 객체를 생성하지만, 이것은 매우 사소한 개선 될 수 있습니다.
  • stormenet처럼 CreateEmail 기능이 병목 현상이 될 수 있습니다. 비동기로 만들 수 있습니다. GetList의 결과를 가정
1

당신이 포함-추가 것들을 속도가 향상됩니다 HashSet의 비교를 건너 뛰는, CreateEmail 전화에 비해 충분히 큰/느립니다.

var requiredLists = 
    Tests.SelectMany(test => this.GetLists(test.test, selectedTag)) 
     .Distinct([Your ListComparer]); 
// or 
var requiredLists = 
    Tests.SelectMany(test => this.GetLists(test.test, selectedTag)) 
     .GroupBy(x => x.Id).SelectMany(x => x.First()); 

foreach (var List in requiredLists) 
{ 
    // (...) 
    OutlookModel.Instance.CreateEmail(toRecipients, ccRecipients, bccRecipients, this.Draft, mailMode, replyTo); 
} 

또한 일을 속도를 PLINQ을 시도 할 수 있지만 아마 COM의 나는, 당신이 CreateEmail 호출에 문제로 실행하는 것 같아요 :) (고유 ([귀하의 ListComparer]) 또는 GROUPBY에 전화를 시도 객체이기 때문에 멀티 스레딩은 번거롭다. GetList가 멀티 쓰레드 오버 헤드의 가치가 있기에 충분히 느리다면, requiredLists을 생성 할 때 첫 번째 호출에서 GetList를 실험 해 볼 수 있습니다.

관련 문제