2014-04-22 4 views
0

번호 :Parallel.ForEach 함수에서 실행 시간을 줄이는 방법은 무엇입니까?

Parallel.ForEach(
    infoMap, 
    map => 
    { 
     var workItem = map.WorkItem; 
     var parentInViews = viewMaps; 
     var workbenchItem = map.WorkbenchItem; 
     string LinkType = string.Empty; 

     WorkItemLinkCollection linkedWorkItems = workItem.WorkItemLinkHistory; 
     if (linkedWorkItems != null && linkedWorkItems.Count > 0) 
      LinkType = linkedWorkItems[0].LinkTypeEnd.LinkType.ReferenceName; 
     else if (workItem != null) 
      LinkType = workItem.Store.WorkItemLinkTypes.LinkTypeEnds["Parent"].LinkType.ReferenceName; 

     if (!string.IsNullOrEmpty(LinkType)) 
     { 
      var viewMap = parentInViews.FirstOrDefault(); 
      if (viewMap != null) 
      { 
       var linkName = LinkType; 
       var childType = viewMap.ChildType; 

       ILinkItem itm = Factory.BuildLinkItem(linkName, workbenchItem, workbenchItem); 
       lock (Addparents) 
       { 
        Addparents.Add(itm); 
       } 
      } 
     } 
    }); 

Factory.BuildLinkItem 정의 :

public static ILinkItem BuildLinkItem(string linkName, IWorkbenchItem parent, IWorkbenchItem child) 
{   
     return new LinkItem { LinkName = linkName ?? string.Empty, Child = child, Parent = parent }; 
} 

658 items는 모두가 존재하고, 상기 기능을 실행 Parallel.ForEach 거의 10초 걸린다.

실행 시간을 줄일 수 있습니까? 그렇다면 해결책을 제안하십시오. 감사.

는 : 어떤 다른 방법은 성능을 향상시키고 또한 실행 시간을 줄일 수있는 경우는 별도로 Parallel.ForEach에서, 제안하십시오. 감사.

+0

당신이 당신의 코드를 프로파일 링과 시간이 소요되는 경우보고 시도? –

+0

설치 권한이 없으므로 코드를 프로파일 링하지 않았습니다. –

+0

왜'Addparents.Add (itm)'을하고 있습니까? '.ToList()'로 병렬 선택을하면 목록에 항목을 넣을 수없는 이유는 무엇입니까? – Enigmativity

답변

1

문제는 lock 문에 있습니다. 그 뒤에있는 mutex 메커니즘은 다른 동기화 메커니즘에 비해 극도로 성능이 비쌉니다. 나는 그 10 초 중 99.99 %를 걸 겠어. 코드는 그 중요한 부분에서 잠그고 기다리고있다. 병렬이 아닌 선택조차도 훨씬 더 빠릅니다.

두 가지 옵션이 있습니다. 먼저 Parallel.ForEach 대신 .AsParallel().Select().Where()을 사용하고 자물쇠 안에 컬렉션을 추가하는 것입니다. 나는 이것을 매우 추천 할 것이다. 이렇게하면 서로 다른 항목의 작업 간 동기화가 자동으로 처리됩니다.

두 번째 옵션은 잠금 및 일반 컬렉션 대신. NET 4에있는 어떤 종류의 concurrent collection을 사용하는 것입니다. 이러한 콜렉션은 스레드 세이프 인 항목을 추가하는 데 특별히 최적화되어 있습니다.

이 작은 해킹, 어떻게 당신은 단순히 AsParallel로 변환 할 수있다 :

infoMap.AsParallel().Select(
map => 
{ 
    var workItem = map.WorkItem; 
    var parentInViews = viewMaps; 
    var workbenchItem = map.WorkbenchItem; 
    string LinkType = string.Empty; 

    WorkItemLinkCollection linkedWorkItems = workItem.WorkItemLinkHistory; 
    if (linkedWorkItems != null && linkedWorkItems.Count > 0) 
     LinkType = linkedWorkItems[0].LinkTypeEnd.LinkType.ReferenceName; 
    else if (workItem != null) 
     LinkType = workItem.Store.WorkItemLinkTypes.LinkTypeEnds["Parent"].LinkType.ReferenceName; 

    if (!string.IsNullOrEmpty(LinkType)) 
    { 
     var viewMap = parentInViews.FirstOrDefault(); 
     if (viewMap != null) 
     { 
      var linkName = LinkType; 
      var childType = viewMap.ChildType; 

      ILinkItem itm = Factory.BuildLinkItem(linkName, workbenchItem, workbenchItem); 

      return new {item = itm, filter=true}; 
     } 
    } 
    return new {item = (ILinkItem)null, filter=false}; 
}) 
.Where(x=>x.filter) 
.Select(x=>x.item) 
.ToList(); 
+0

내 코드를 업데이트하고 첫 번째 옵션 인'우선 .AsParallel() .Select() 및 .Where()'를 사용하여 코드를 업데이트 할 수 있습니까? 감사. –

+0

@ 존 스티븐 나는 시도했다. 그것이 작동하는지 확실하지 않습니다. – Euphoric

+0

@ 유언 - 어떻게 작동하는지 확신 할 수 없습니까? 작품이든 아니든 작품입니다. 그렇지 않다면 옳지 않은 것은 무엇입니까? 오류가 무엇입니까? – Enigmativity