Slow ResultBuffer

Slow ResultBuffer

office
Enthusiast Enthusiast
1,462 Views
4 Replies
Message 1 of 5

Slow ResultBuffer

office
Enthusiast
Enthusiast

I want to save a lot of data in DWG via XRecord but when making the ResultBuffer for it, it is very slow.

Here is a sample code for the ResultBuffer:

 

        public static void SaveSurfaceDataToDictionary(string dictName)
        {
            ResultBuffer resultBuffer = new ResultBuffer();
            foreach (long objectHandle in Lisp.plineHandleList) //List length = 59260
            {
                resultBuffer.Add(new TypedValue((int)DxfCode.Handle, objectHandle));
            }
            SetXrecord(dictName, "ObjectHandleList", resultBuffer);

            resultBuffer = new ResultBuffer();
            foreach (TriangleNet.Geometry.Vertex v in Lisp.polygonList.Points) //List length = 22766
            {
                resultBuffer.Add(new TypedValue((int)DxfCode.UcsOrg, new Point3d(v.X, v.Y, v.Z)));
            }
            SetXrecord(dictName, "PolygonPointsList", resultBuffer);

            resultBuffer = new ResultBuffer();
            List<ISegment> segmentList = Lisp.polygonList.Segments;
            foreach (Segment segment in segmentList) //List length = 17022
            {
                TriangleNet.Geometry.Vertex v;
                v = segment.GetVertex(0);
                resultBuffer.Add(new TypedValue((int)DxfCode.UcsOrg, new Point3d(v.X, v.Y, v.Z)));
                v = segment.GetVertex(1);
                resultBuffer.Add(new TypedValue((int)DxfCode.UcsOrg, new Point3d(v.X, v.Y, v.Z)));
            }
            SetXrecord(dictName, "PolygonSegmentsList", resultBuffer);
        }
        public static void SetXrecord(string dictName, string key, ResultBuffer resbuf)
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                DBDictionary NOD =
                    (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
                DBDictionary dict;
                if (NOD.Contains(dictName))
                {
                    dict = (DBDictionary)tr.GetObject(NOD.GetAt(dictName), OpenMode.ForWrite);
                }
                else
                {
                    dict = new DBDictionary();
                    NOD.UpgradeOpen();
                    NOD.SetAt(dictName, dict);
                    tr.AddNewlyCreatedDBObject(dict, true);
                }
                Xrecord xRec = new Xrecord();
                xRec.Data = resbuf;
                dict.SetAt(key, xRec);
                tr.AddNewlyCreatedDBObject(xRec, true);
                tr.Commit();
            }
        }

 

The ResultBuffer operation takes 12 seconds. Way to slow.

 

Any idea or alternative for this?

I want to keep my data in DWG database.

0 Likes
Accepted solutions (1)
1,463 Views
4 Replies
Replies (4)
Message 2 of 5

_gile
Consultant
Consultant

Hi,

 

Except the fact you could start the transaction and get or or create the dictionary only once in the SaveSurfaceDataToDictionary() method ans pass them to the SetXrecord() method I do not see anything unefficient in your code structure.

But we do not know anything about the custom objects you use (Lisp, TriangleNet.Geometry.Vertex, Segment). The implementation of these types may be the cause of the slow down.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 5

office
Enthusiast
Enthusiast

The custom objects are alright.

The problem is the resultbuffer.

Here is a sample code which takes 21 seconds without any implementations:

        public static void SaveSurfaceDataToDictionary(string dictName)
        {
            ResultBuffer resultBuffer = new ResultBuffer();
            for (int i = 0; i < 50000; i++)
            {
                resultBuffer.Add(new TypedValue((int)DxfCode.Int32, i));
            }

            resultBuffer = new ResultBuffer();
            for (int i = 0; i < 50000; i++)
            {
                resultBuffer.Add(new TypedValue((int)DxfCode.Int32, i));
            }

            resultBuffer = new ResultBuffer();
            for (int i = 0; i < 50000; i++)
            {
                resultBuffer.Add(new TypedValue((int)DxfCode.Int32, i));
            }
        }
0 Likes
Message 4 of 5

_gile
Consultant
Consultant
Accepted solution

I made some tests and it looks like it is the Resultbuffer.Add() method which is very slow.

You should use the overload ResultBuffer(params TypedValue[])  constructor instead.

        [CommandMethod("BENCH")]
        public static void Bench()
        {
            var ed = Application.DocumentManager.MdiActiveDocument.Editor;
            BenchArray(ed);
            BenchAdd(ed);
        }

        public static void BenchArray(Editor ed)
        {
            var sw = new Stopwatch();
            sw.Start();
            var tvs = new TypedValue[50000];
            for (int i = 0; i < 50000; i++)
            {
                tvs[i] = new TypedValue((int)DxfCode.Int32, i);
            }
            ResultBuffer resbuf = new ResultBuffer(tvs);
            sw.Stop();
            ed.WriteMessage($"\nElapsed milliseconds to build from a TypedValues array: {sw.ElapsedMilliseconds}");
        }

        public static void BenchAdd(Editor ed)
        {
            var sw = new Stopwatch();
            sw.Start();
            var resbuf = new ResultBuffer();
            for (int i = 0; i < 50000; i++)
            {
                resbuf.Add(new TypedValue((int)DxfCode.Int32, i));
            }
            sw.Stop();
            ed.WriteMessage($"\nElapsed milliseconds to add 50000 TypedValues: {sw.ElapsedMilliseconds}");
        }

Gives:

Elapsed milliseconds to build from a TypedValues array: 18
Elapsed milliseconds to add 50000 TypedValues: 3734

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 5

office
Enthusiast
Enthusiast

Nice solution.

Now I can save my large data using the ResultBuffer in 0.2 seconds instead of 12 seconds.

Thank you very much for the solution 🙂

0 Likes