Replace Path Component in Grasshopper is extremly slow? (13.9 KB)


when using the ReplacePath Component I realize it is a real bottleneck in my definitions.

Here You find a definition that creates lots of Paths: the calculation of CurveClosestPoint(which I believe to do heavy computing) needs no time in Comparison to ReplacePath. If the count of paths grow, at some point GH gets unuseable.

Is there a chance to get ReplacePath to work with many paths?


I don’t want to rush anyone, but the ReplacePath-Components uses more than half of the calculation time (150+ seconds) in the definition that I use every day.

Will someone take a look at it?


haven’t tested it much, but this already greatly improves performance. Assuming you use it as your example shows: (14.7 KB)

  if (newPaths == null || data == null)
      throw new ArgumentException("Argument must not be null");

    // make it flat
    var paths = newPaths.AllData();

    // check input type
    if (paths.Count == 0 || !(paths[0] is GH_Path))
      throw new ArgumentException("Provided paths count must not be zero and have to be of Type GH_Path");

    // check length equality
    if (paths.Count != data.BranchCount)
      throw new ArgumentException("Paths have to match in size");

    // create a new tree
    DataTree<object> newDataTree= new DataTree<object>();

    // and fill it
    for (int i = 0; i < data.Paths.Count; i++)
      newDataTree.AddRange(data.Branch(i), (GH_Path) paths[i]);

    newTree = newDataTree;

Thank You Tom,
its definitely faster now!

I am not fit in C#, but when I read the comments, it appears to me that You flatten the input first and then copy it into a new tree.
I have 2 (elaborately determined) lists of paths to be replaced (from+to) but not all path names occur in data. How could this be solved?

BTW: It seems to me that the Path Mapper has no delay at all (or the profiler doesn’t display it), so I believe the logic of renaming paths could be still accelerated (in the grasshopper program, probably best by David Rutten?).

Sure you can even more improve the performance. I was not even trying this.

DataTrees are special constructs for GH script components. Usually you access and modify data a bit different on plugin level. Just compililing it as an plugin makes it faster, and probally applying this logic directly to an GH_Structure.

Bytheway, I’m not flatten the tree, i just get all data in a list, but the paths remain intact. You cannot edit the paths of an existing data tree, and memory is not the issue here. We are talking about speed.

In the end the bottleneck is not the replace path component, but rather the need to use that. What is the reason for this? I was never in need to replace my paths.

Hello Tom,

I import several CAD-objects (of different complexity) in Rhino and read them into GH, and to seperate and number them properly it is quite comfortable to use paths. Sometimes 2 Objects get combined, and then I need to adjust the tree path. (there are in fact many cases where I have to change paths). Apart from the time-loss this approach works well and is intuitive to work with.

But since Your script is somewhat faster than the original ReplacePath, is it possible to read the paths of the existing tree to make the replacement?

I believe its possible with my implementation. I don’t fully understand that question to be honest. You just need to feed in a full list of new paths. This means, get the old paths like you do in your example and replace the path at the correct indices, essentially what the jitter component does for you. Its simple list manipulation.

As alternative, did you know, that you can group and ungroup geometries? If you group multiple entities into one, you can deal with this as a flat list. The index in that list is then the identifier for your group. Working with groups is quite handy.

A very simplified example (the 2 Trees can contain 1000+ Branches):
At the moment I have 2 Lists
“from” --> “to”
{0;1} {0;1}
{0;2} {0;3}
{0;3} {0;3}
{0;4} {0;4}
{0;5} {0;5}
{0;6} {0;5}

the Input Tree with the Data to convert is:
{0;3} [ x ]
{0;5} [ y ]
{0;6} [ z ]

The Output Tree of the new data would then be:
{0;3} [ x ]
{0;5} [ y,z ]

but if there is no chance I somehow try to filter the Replace-List to match the input.

Maybe tommorow…

Does this work for you? (18.3 KB)


This is great!!
the first attempts were successful, even with empty Paths.

Thank You very very much!