0

Code:

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 definition:

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

Totally 658 items are present and it takes nearly 10 seconds to execute the above Parallel.ForEach function.

Is it possible to reduce the execution time and if so, please suggest me a solution. Thanks.

Note: Apart from Parallel.ForEach, if any alternate method is there to increase the performance and reduce the execution time also, Please suggest. Thanks.

6
  • Have you tried profiling your code and seeing where the time is spent? Commented Apr 22, 2014 at 5:17
  • Since, I don't have access to install, I haven't profile the code. Commented Apr 22, 2014 at 5:21
  • Why are you doing Addparents.Add(itm)? Why not do a parallel select with a .ToList() to put the items in a list? Commented Apr 22, 2014 at 5:26
  • @Enigmativity I guess because writing this kind of code is much more straightforward than combination of multiple Select() and Where() with all that state. Commented Apr 22, 2014 at 5:28
  • @Enigmativity, how to change the Addparents.Add(itm); to parallel select with a .ToList(). Thanks. Commented Apr 22, 2014 at 5:29

1 Answer 1

1

Your problem is in the lock statement. The mutex mechanism behind it is extremely performance expensive compared to other synchronization mechanisms. I'm gonna bet 99.99% of those 10 seconds, the code spends locking and waiting in that critical section. Even non-parallel select would be much faster.

Your have two options. First is to use .AsParallel() .Select() and .Where() instead of Parallel.ForEach and adding into a collection inside a lock. I would highly recommend this. This way, the synchronization between operation on different items is handled automatically.

Second option is to use some kind of concurrent collection that exist in .NET 4 instead of locking and normal collection. Those collections are specially optimized to extra quick adding of items, that is threadsafe.

This is little hack, how could you simply convert it to 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();
Sign up to request clarification or add additional context in comments.

9 Comments

Can you update my code and change it accordingly your first option First is to use .AsParallel() .Select() and .Where(). Thanks.
@Euphoric - How can you be not sure that it is working. Either is works or it doesn't. If it doesn't, what's not going right? What's the error?
@Euphoric, I tried .AsParallel() .Select() and .Where() approach and it works fine. But, when compared to the Parallel.ForEach approach, In multiple times, the milliseconds is little higher. I used System.Diagnostics.StopWatch to test both set of codes for the execution time comparision. Finally, I am going to stick with the Parallel.ForEach approach, which is having less execution time in most times I tested when compared to .AsParallel() .Select() and .Where() approach. Thank You for your valuable suggestion and solution.
@JohnStephen You mean compared to your code? You sure you are testing correctly? If that is the case, then there is something wrong, because there is nothing in your code that would suggest it would take 10 seconds for 658 items. Other things that catch my mind is Factory.BuildLinkItem or possible lazy loading if you are using entity framework.
@Euphoric, Yes, I compared with my code and I am sure that I tested correctly. Also, If Factory.BuildLinkItem might be a problem in this case, whether can we have any other workaround instead of using Factory.BuildLinkItem. Thanks. Following is the Factory.BuildLinkItem definition. public static ILinkItem BuildLinkItem(string linkName, IWorkbenchItem parent, IWorkbenchItem child) { return new LinkItem { LinkName = linkName ?? string.Empty, Child = child, Parent = parent }; }
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.