Click here to Skip to main content
15,867,568 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
This is my code in which a list contains 2 more lists where the WorkItem collection contains a large number of records such as 7,000 it takes 10 min. Is there any way to make it faster and in case it's deciding the workItem type if it's a bug, task or product backlog item. Please tell me how to make the looping faster. It's taking 10 min to loop 7,000 records can we use threading to make it faster?
var workItemList = new List<WorkItemViewModel>();

           for (int i = 0; i < workItemCollection.Count; i++)
           {
               var workItem = workItemCollection[i];

               if (workItem.Type.Name == "Product Backlog Item")
               {
                   var model = new WorkItemViewModel()
                   {


                       FID = (workItem.WorkItemLinks.Count > 0) ? ((workItem.WorkItemLinks[0].LinkTypeEnd.Name.ToString() != "Child") ? workItem.WorkItemLinks[0].TargetId : 0) : 0,

                       ID = workItem.Id,
                       Name = workItem.Title,
                       State = workItem.State,

                       priorty = Convert.ToInt32(workItem.Fields["Priority"].Value),
                       //   Size =(int) workItem.Fields["Size"].Value ,
                       Size = Convert.ToInt32(workItem.Fields["Effort"].Value),

                       StoryPoints = Convert.ToInt32(workItem.Fields["Story Points"].Value),
                       DoneStatus = workItem.Fields["Done Status"].Value.ToString(),
                       StoryOwner = workItem.Fields["Story Owner"].Value.ToString(),
                       Assignedto = workItem.Fields["Assigned To"].Value.ToString(),
                       StoryAuthor = workItem.Fields["Story Author"].Value.ToString(),
                       IterationPath = workItem.IterationPath
                   };

                   workItemList.Add(model);
               }
               else
               {
                   switch (workItem.Type.Name)
                   {
                       case "Task":
                           var task = new TFSTask()
                           {
                               Storyid = (workItem.WorkItemLinks.Count > 0) ? workItem.WorkItemLinks[0].TargetId : 0,
                               ID = workItem.Id,
                               name = workItem.Title,
                               //activity = workItem.Fields["MyCompany.Activity"].Value.ToString(),
                               //start = (DateTime?)workItem.Fields["MyCompany.ActivityStart"].Value,
                               //due = (DateTime?)workItem.Fields["MyCompany.ActivityFinish"].Value,
                               status = workItem.State,
                               IterationPath = workItem.IterationPath,
                               Assignedto = workItem.Fields["Assigned To"].Value.ToString(),

                               priorty = Convert.ToInt32(workItem.Fields["Priority"].Value),
                               effort = Convert.ToInt32(workItem.Fields["effort"].Value),
                               Completed = Convert.ToInt32(workItem.Fields["Completed"].Value)

                           };
                           if (task.Storyid != 0)
                           {
                               workItemList.Last().Tasks.Add(task);
                           }


                           break;
                       case "Bug":
                           var bug = new TFSIssue()
                           {
                               Storyid = (workItem.WorkItemLinks.Count > 0) ? workItem.WorkItemLinks[0].TargetId : 0,
                               ID = workItem.Id,
                               Name = workItem.Title,
                               //start = (DateTime?)workItem.Fields["MyCompany.ActivityStart"].Value,
                               //due = (DateTime?)workItem.Fields["MyCompany.ActivityFinish"].Value,
                               State = workItem.State,
                               IterationPath = workItem.IterationPath,
                               Assignedto = workItem.Fields["Assigned To"].Value.ToString(),

                               priorty = Convert.ToInt32(workItem.Fields["Priority"].Value),
                               effort = Convert.ToInt32(workItem.Fields["effort"].Value),
                               // Completed = Convert.ToInt32(workItem.Fields["Completed"].Value)
                           };
                           if (bug.Storyid != 0)
                           {
                               workItemList.Last().Issues.Add(bug);
                           }
                           break;



                       default:
                           break;
                   }
               }
           }

public class WorkItemViewModel
   {
       public string Name { get; set; }
       public int ID { get; set; }

       public string State { get; set; }
       // public DateTime? due { get; set; }
       public int priorty { get; set; }
       public int Size { get; set; }
       //  public int effort { get; set; }
       public int StoryPoints { get; set; }
       public string DoneStatus { get; set; }
       public string StoryOwner { get; set; }
       public string Assignedto { get; set; }
       public string StoryAuthor { get; set; }
       public string IterationPath { get; set; }
       public int FID { get; set; }
       public List<TFSIssue> Issues { get; set; }
       public List<TFSTask> Tasks { get; set; }

       public WorkItemViewModel()  // Added a public constructor
       {
           Issues = new List<TFSIssue>();
           Tasks = new List<TFSTask>();

       }

   }


What I have tried:

A list containing 2 more lists works slow in looping can i use Thread to make this faster?
Posted
Updated 24-Feb-18 1:59am
v4
Comments
BillWoodruff 24-Feb-18 6:04am    
Your first goal might be to try and reduce the number of Records you process by filtering what you pull from your database.
Akhil Jain 24-Feb-18 6:24am    
not possible !!
Richard MacCutchan 24-Feb-18 8:50am    
Threading will not help until you fix the issues identified below. And even then there is no guarantee that it will run faster.

C#
(workItem.WorkItemLinks[0].LinkTypeEnd.Name.ToString()
Why calling ToString() on a member which is already a string? This question also holds for other ToString() usages in your code.

C#
Size = Convert.ToInt32(workItem.Fields["Effort"].Value)
Convert class shows really poor performance compared to built-in parsing functions. Always use Parse or TryParse methods when you want to get an integral value from a string. For example, above snippet could be replaced with
C#
Size = int.Parse(workItem.Fields["Effort"].Value)

Furthermore, if Value would already be of type int, there would not be any need for parsing at all. Not knowing the definition of your WorkItemViewModel class, this is just an assumption.

I am not saying that your code could not benefit from a multithreaded treatment, but if performance is your concern, then better handle basic operations avoiding unnecessary ToString calls and usages of Convert class.

Just my 2 cents. Hope this helps.
 
Share this answer
 
Comments
Akhil Jain 24-Feb-18 7:07am    
have put stopwatch before and after the loop and it show's 10 min
Akhil Jain 24-Feb-18 7:08am    
can't i use threading it will just reduce 2 min (to string and value)!!
phil.o 24-Feb-18 7:17am    
Yes, you can. But you should adopt good practices in the first place and avoid performing unnecessary calls and poor-performance-classes like Convert.
8 min instead of 10 is already a 20% improvement in performance, that is not negligible.
phil.o 24-Feb-18 7:38am    
Moreover, having a deeper look at your code, why using workItem.Fields["Priority"].Value when you could write workItem.priorty? (typo inherited from the code you have shown)
Akhil Jain 24-Feb-18 7:52am    
it's value there in fields and not workItem.priorty
If you are serious about understanding time performance in .NET, I suggest you learn to use one of these open-source tools: BenchmarkDotNet (what I use) [^], or, AppMetrics [^]. By doing this, you will become a better programmer. Scott Hanselman wrote about BenchMark in 2016: [^]. Both these projects are actively maintained.

Without understanding the structure of the database here, our ability to help you is, imho, limited to the kinds of (excellent) suggestions that phil.o posted.

Assuming you can't modify the database, the biggest problem I see is that you are creating new objects piece-by-piece instead of mapping a datatable directly to an instance of a Class that holds a collection of instances of your record-to-object.

Take a look at this CP article for an overview: [^]

Explore Features in Linq that may be relevant: [^]
 
Share this answer
 
v3
Comments
phil.o 24-Feb-18 8:15am    
Thank you Bill. Nice advises, too.
I see nothing obvious.
You need to understand where and how time is spent, the tool of choice is a profiler.
Profiling (computer programming) - Wikipedia[^]
List of performance analysis tools - Wikipedia[^]

[Update]
Quote:
have put stopwatch before and after the loop and it show's 10 min

'Understanding how time is spend' means measuring time spend on each line of code to understand which one consume the most time.
 
Share this answer
 
v2
Comments
Akhil Jain 24-Feb-18 6:46am    
can't i use threading ?
Patrice T 24-Feb-18 6:51am    
The answer depend on how time is spent.
Akhil Jain 24-Feb-18 7:07am    
have put stopwatch before and after the loop and it show's 10 min

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900