Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6344589
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T20:40:15+00:00 2026-05-24T20:40:15+00:00

I need to traverse a tree quickly, and I would like to do it

  • 0

I need to traverse a tree quickly, and I would like to do it in parallel. I’d rather use the parallel extensions than manually spin up a bunch of threads.

My current code looks something like this:

public void Traverse(Node root)
{
    var nodeQueue = new Queue<Node>();
    nodeQueue.Enqueue(root);
    while (nodeQueue.Count != 0)
    {
        var node = nodeQueue.Dequeue();
        if (node.Property == someValue) DoSomething(node);
        foreach (var node in node.Children)
        {
            nodeQueue.Enqueue(node);
        }
    }
}

I was really hoping that Parallel.ForEach had a Parallel.While analog. I came across Stephen Toub’s article on Implementing Parallel While with Parallel.ForEach. If read it correctly this still won’t work because I am mutating the queue I am trying to iterate.

Do I need to use a task factory and recursion (and is that risky?) ? or is there some simple solution I am overlooking?

@svick:

The tree has just over 250,000 nodes.
The maximum depth right now is 14 nodes deep including the root.

There are about 500 nodes off the root, and the balance after that has a fairly random distribution.
I’ll get some better stats on the distribution soon.

@Enigmativity:

Yes, the tree is being modified, concurrently by many users, but I will usually have a shared read lock for the tree or sub tree, or allow for dirty reads.

Calls to node.Children can be considered atomic.

DoSomething is really one of several delegates, for some expensive operations I will probably gather a snapshot list of nodes and process them outside the traversal.

I realized that I should probably look at the general case (a sub-tree being traversed instead of the entire tree.) To that end I ran traverse on every node of the tree and looked at the total time.

I used a Parallel.ForEach(nodes, Traverse) for each traversal algorithm, where nodes contained all ~250k nodes. This simulated (sort of) a lot of users simultaneously requesting a lot of different nodes.

00256ms Breadth First Sequential

00323ms Breadth First Sequential with work (i incremented a static counter as "work")

01495ms Kirks First answer

01143ms Svicks Second answer

00000ms Recursive Single Threaded didn’t finish after 60s

00000ms Enigmativity’s answer didn’t finish after 60s

@Enigmativity, I think it’s possible I might have messed up your algorithm somehow, because it seems like it should be much quicker.

The results surprised me to say the least.
I had to add some work to the breadth first sequential just to convince myself that the compiler wasn’t magically optimizing away the traversals.

For the single traversal of the head, parallelizing the first level only had the best performance. But just barely, this number improved as I added more nodes to the second level (2000 instead of 500).

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T20:40:16+00:00Added an answer on May 24, 2026 at 8:40 pm

    The most direct way would be to create a Task for each child node and then wait for all of them:

    public void Traverse(Node root)
    {
        if (node.Property == someValue)
            DoSomething(node);
    
        var tasks = new List<Task>();
    
        foreach (var node in node.Children)
        {
            // tmp is necessary because of the way closures close over loop variables
            var tmp = node;
            tasks.Add(Task.Factory.StartNew(() => Traverse(tmp)));
        }
    
        Task.WaitAll(tasks.ToArray());
    }
    

    Task is fairly light-weight, so creating lots of them works reasonably well. But they do have some overhead, so doing something more complicated like having a few tasks that share a queue is probably going to be faster. If that’s the way you’re going to go, don’t forget that empty queue doesn’t mean all work is done. Classes from the System.Collections.Concurrent namespace are going to come handy if you went this way.

    EDIT: Because of the shape of the tree (the root has about 500 children), processing just the first level in parallel should give good performance:

    public void Traverse(Node root, bool parallel = true)
    {
        if (node.Property == someValue)
            DoSomething(node);
    
        if (parallel)
        {
            Parallel.ForEach(node.Children, node =>
            {
                Traverse(node, false);
            });
        }
        else
        {
            foreach (var node in node.Children)
            {
                Traverse(node, false);
            }
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I need to traverse a binary tree, skipping the children of any node for
I need a way to traverse a LINQ-to-SQL expression tree to extract the table
I need to recursively traverse a directory and create a tree to be used
If you need to recursively traverse a directory tree, there are two ways to
I've got a 1-based array of four items which I need to traverse. For
Need a function like: function isGoogleURL(url) { ... } that returns true iff URL
I have this python code that will traverse a tree structure. I am trying
The Zipper data structure is great when one wants to traverse a tree and
I have a large filesystem that I need to traverse for errors. Each file
I have an LDAP subtree, whose entries correspond to a tree-like structure of Java

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.