Code fast in grasshopper script C# but very slow in Visual studio


(Youssef Aboualghar) #1

So I was making this code in a script in c# It went just fine, about 339ms.
When I wrote it in my plugin speed went down quite a bit, it became 2500ms

I’m I wondering what’s causing that much delay ? I thought it should work faster.

Here is the script in GH
GHScript.gh (162.7 KB)

Here is the same code in VS

using System;
using System.Collections.Generic;
using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;
using Rhino.Geometry;

namespace SurfaceTrails2.Composite
{
public class _28_11_18_Composite_3D_01 : GH_Component
{
///


/// Initializes a new instance of the _1_11_18_Composite_3D_01 class.
///

public _28_11_18_Composite_3D_01()
: base(“Composit 3D”, “Composite3D”,
“Creates YFA composite lines with respect to it’s thickness and 3d Boundary”,
“YFAtools”, “Composite”)
{
}

    /// <summary>
    /// Registers all the input parameters for this component.
    /// </summary>
    protected override void RegisterInputParams(GH_InputParamManager pManager)
    {
        pManager.AddMeshParameter("mesh", "m", "Mesh to make the YFA composite system on", GH_ParamAccess.list);
        pManager[0].DataMapping = GH_DataMapping.Flatten;
        pManager.AddNumberParameter("Naked edge length", "length", "Length of edge on the naked sides of the brep", GH_ParamAccess.item, 0.05);
        pManager.AddNumberParameter("Clothed edge width", "width", "width of edge on the clothed sides of the brep", GH_ParamAccess.item, 0.01);
    }

    /// <summary>
    /// Registers all the output parameters for this component.
    /// </summary>
    protected override void RegisterOutputParams(GH_OutputParamManager pManager)
    {
        pManager.AddPointParameter("Composite points", "pt", "pt", GH_ParamAccess.tree);
        pManager.HideParameter(0);
        pManager.AddCurveParameter("crv", "Composite curve", "crv", GH_ParamAccess.tree);
    }

    /// <summary>
    /// This is the method that actually does the work.
    /// </summary>
    /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
    protected override void SolveInstance(IGH_DataAccess DA)
    {
        var meshes = new List<Mesh>();
        double nakedLength = 0.05;
        double clothedWidth = 0.01;

        if (!DA.GetDataList(0, meshes)) return;
        if (!DA.GetData(1, ref nakedLength)) return;
        if (!DA.GetData(2, ref clothedWidth)) return;

        var edgeTopology = new List<GH_Integer>();
        var allEdges = new List<GH_Curve>();

        var pts = new GH_Structure<GH_Point>();
        var joinedEdgesTree = new GH_Structure<GH_Curve>();

        int b = 0;

        foreach (var mesh in meshes)
        {
            for (int i = 0; i < mesh.TopologyEdges.Count; i++)
            {
                edgeTopology.Add(new GH_Integer(mesh.TopologyEdges.GetConnectedFaces(i).Length));
                allEdges.Add(new GH_Curve(mesh.TopologyEdges.EdgeLine(i).ToNurbsCurve()));
            }
            var allEdgesTree = ListOperations.ReOrganize(ListOperations.PartitionToTree(allEdges, 3));
            var edgeTopologyTree = ListOperations.ReOrganize(ListOperations.PartitionToTree(edgeTopology, 3));

            for (int i = 0; i < allEdgesTree.PathCount; i++)
            {
                for (int j = 0; j < allEdgesTree.get_Branch(i).Count; j++)
                {
                    var GHNurbs =(GH_Curve)allEdgesTree.get_Branch(i)[j];
                    var nurbs = GHNurbs.Value/*.ToNurbsCurve()*/;
                    var GHInteger = (GH_Integer) edgeTopologyTree.get_Branch(i)[j];

                    Point3d pt1;
                    Point3d pt2;
                    if (GHInteger.Value != 1)
                    {
                        pt1 = nurbs.PointAtLength(nurbs.GetLength() * 0.5 + clothedWidth * 0.5);
                        pt2 = nurbs.PointAtLength(nurbs.GetLength() * 0.5 - clothedWidth * 0.5);
                        pts.Append(new GH_Point(pt1), new GH_Path(b,i));
                        pts.Append(new GH_Point(pt2), new GH_Path(b,i));
                    }
                    else
                    {
                        pt1 = nurbs.PointAtLength(nurbs.GetLength() * 0.5 + nakedLength * 0.5);
                        pt2 = nurbs.PointAtLength(nurbs.GetLength() * 0.5 - nakedLength * 0.5);
                        pts.Append(new GH_Point(pt1), new GH_Path(b, i));
                        pts.Append(new GH_Point(pt2), new GH_Path(b, i));
                    }
                }
            }
            allEdges.Clear();
            edgeTopology.Clear();

            for (int i = 0; i < allEdgesTree.PathCount; i++)
            {
           var GHCurveList= allEdgesTree.get_Branch(i);
                var curveList = new List<Curve>();
                foreach (GH_Curve ghCurve in GHCurveList)
                {
                    curveList.Add(ghCurve.Value);
                }
                 joinedEdgesTree.Append(new GH_Curve(Curve.JoinCurves(curveList)[0]), new GH_Path(b, i));
             }

            for (int i = 0; i < joinedEdgesTree.PathCount; i++)
            {
                for (int j = 0; j < joinedEdgesTree.get_Branch(i).Count; j++)
                {
                    var GHCurveList = joinedEdgesTree.get_Branch(i);
                    var curveList = new List<Curve>();
                    foreach (GH_Curve ghCurve in GHCurveList)
                    {
                        curveList.Add(ghCurve.Value);
                    }

                    var GHptList = pts.get_Branch(i);
                    var ptList = new List<Point3d>();
                    foreach (GH_Point ghPt in GHptList)
                    {
                        ptList.Add(ghPt.Value);
                    }


                    var sortedPoints = PointOperations.SortAlongCurve(curveList[0], ptList);
                        joinedEdgesTree.get_Branch(i)[j] =new GH_Curve(CurveOperations.ClosedPolylineFromPoints(sortedPoints)); ;
                }
            }
            b++;
        }
        var x = pts;
        var y = joinedEdgesTree;

        DA.SetDataTree(0, x);
        DA.SetDataTree(1, y);
    }

   
    /// <summary>
    /// Provides an Icon for the component.
    /// </summary>
    protected override System.Drawing.Bitmap Icon
    {
        get
        {
            //You can add image files to your project resources and access them like this:
            // return Resources.IconForThisComponent;
            return null;
        }
    }

    /// <summary>
    /// Gets the unique ID for this component. Do not change this ID after release.
    /// </summary>
    public override Guid ComponentGuid
    {
        get { return new Guid("f55238f7-25c9-4468-92c3-7d78622584de"); }
    }
}

}

PS: all methods shown in the VS code unknown are already defined with the same name in the GH script.


(David Rutten) #2

Both the script components and VS compile the code, so there should not be a significant difference in performance. The script components always compile debug versions though to give more accurate line readings for exceptions, but that rarely makes a big difference.

You’re using GH_Integer and GH_Curve and such in the VS code, and I assume in the script component you just used int and Curve. If true, that means you are comparing wholly different code.

You can accurately measure the time taken doing certain things using the System.Diagnostics.Stopwatch class. This will let you figure out where in your code the bottlenecks are. Start with some coarse measurements and then narrow it down to smaller and smaller blocks of code.