Author Topic: Slow iteration on ObjectIds  (Read 11817 times)

0 Members and 1 Guest are viewing this topic.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Slow iteration on ObjectIds
« on: August 25, 2011, 03:09:37 AM »
Hello,
  • Windows XP SP3 x86 Rus
  • .Net Framework 3.5 SP1
  • AutoCAD 2009 SP3 x86 Enu
I have are problem - slow ObjectIds iteration in Database. The size of a checked dwg-file is 23 Mb.

Slow code:

Code: [Select]
[CommandMethod("SlowIteration", CommandFlags.Modal)]
public void SlowIteration() {
    Document dwg = acad.DocumentManager.MdiActiveDocument;
    Database TargetDb = dwg.Database;
    Editor ed = dwg.Editor;
    DateTime start = DateTime.Now;

    long amount = 0;//common counter
    long exceptCount = 0;//exception counter

    using (Transaction t = TargetDb.TransactionManager.StartTransaction()) {
        for (long i = TargetDb.BlockTableId.Handle.Value; i < TargetDb.Handseed.Value; i++) {
            ++amount;
            ObjectId id = ObjectId.Null;

            //Slow code begin:
            try {
                id = TargetDb.GetObjectId(false, new Handle(i), 0);
            }
            catch {
                ++exceptCount;
                continue;
            }
            //Slow code end.

        }
    }
    TimeSpan len = DateTime.Now - start;
    ed.WriteMessage(string.Format("Amount: {0}\nSlow iteration time: {1} min. {2} sec.\n",
        amount, len.Minutes, len.Seconds));
}

SlowIteration command result:

Quote from: AutoCAD 2009
Command: SlowIteration
Amount: 517579
Slow iteration time: 4 min. 36 sec.

I have marked problem code location comments.
If to comment out the slow code the result will be another. Below sample.

Fast code:

Code: [Select]
[CommandMethod("FastIteration", CommandFlags.Modal)]
public void FastIteration() {
    Document dwg = acad.DocumentManager.MdiActiveDocument;
    Database TargetDb = dwg.Database;
    Editor ed = dwg.Editor;
    DateTime start = DateTime.Now;

    long amount = 0;//common counter
    //long exceptCount = 0;//exception counter

    using (Transaction t = TargetDb.TransactionManager.StartTransaction()) {
        for (long i = TargetDb.BlockTableId.Handle.Value; i < TargetDb.Handseed.Value; i++) {
            ++amount;
            ObjectId id = ObjectId.Null;
            //Below slow code is commented:
            //try {
            //    id = TargetDb.GetObjectId(false, new Handle(i), 0);
            //}
            //catch {
            //    ++exceptCount;
            //    continue;
            //}
        }
    }
    TimeSpan len = DateTime.Now - start;
    ed.WriteMessage(string.Format("Amount: {0}\nFast iteration time: {1} min. {2} sec.\n",
        amount, len.Minutes, len.Seconds));
}


FastIteration command result:

Quote from: AutoCAD 2009
Command: FastIteration
Amount: 517579
Fast iteration time: 0 min. 0 sec.

I need get all ObjectIds from Database object. How can I get it without slow iteration?

I thank for attention.

kaefer

  • Guest
Re: Slow iteration on ObjectIds
« Reply #1 on: August 25, 2011, 05:44:54 AM »
Hi Andrey,

what you're doing there doesn't look like it's guaranteed to work at all. So you're basically on your own and you've been lucky so far.

That being said, I could think of a few optimizations:
- Get rid of try/catch in a  tight loop, and
- Try to enumerate ObjectId instead of Handle, using the fact that ObjectId is IntPtr under the hood.

A quick mock-up in F# gets the same "Approx. number of objects" as MgdDbgSnoopDb would display. What's missing is the code for generating a new Entity to ensure (entlast) gets the highest number.

Code: [Select]
let test1() =
    let ed = Application.DocumentManager.MdiActiveDocument.Editor
    let db = HostApplicationServices.WorkingDatabase
    use tr = db.TransactionManager.StartTransaction()

    let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
    let entLast = Autodesk.AutoCAD.Internal.Utils.EntLast()
    if entLast.IsNull then
        ed.WriteMessage("\nNo objects in drawing. ")
    else
        let start = (int64) bt.ObjectId.OldIdPtr
        let stop = (int64) entLast.OldIdPtr
        let cnt = ref 0
        let sw = System.Diagnostics.Stopwatch.StartNew()
        for ptr in start .. 4L .. stop do
            let oid = new ObjectId(nativeint ptr)
            if oid.IsValid then
                incr cnt
        sw.Stop()       
       
        ed.WriteMessage("\n{0} objects in drawing, time elapsed: {1} ", !cnt, sw.Elapsed)
           
    tr.Commit()

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #2 on: August 25, 2011, 06:20:43 AM »
what you're doing there doesn't look like it's guaranteed to work at all. So you're basically on your own and you've been lucky so far.
I use this approach for a long time and it always works successfully, but slowly... :(((

Which library I must add to my project for Autodesk.AutoCAD.Internal.Utils.EntLast() using?
« Last Edit: August 25, 2011, 06:25:14 AM by Andrey »

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #3 on: August 25, 2011, 06:28:39 AM »
I has found: C:\Program Files\AutoCAD 2009\acmgdinternal.dll

kaefer

  • Guest
Re: Slow iteration on ObjectIds
« Reply #4 on: August 25, 2011, 06:29:56 AM »
Which library I must add to my project for Autodesk.AutoCAD.Internal.Utils.EntLast() using?

Eh, acmgdinternal.dll, perhaps?  (You said you're on 17.2. Since18.0 it's integrated in AcMgd.dll.)

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #5 on: August 25, 2011, 07:00:32 AM »
Eh, acmgdinternal.dll, perhaps?  (You said you're on 17.2. Since18.0 it's integrated in AcMgd.dll.)
Thank you.

Code: [Select]
[CommandMethod("KaefersIteration", CommandFlags.Modal)]
public void KaefersIteration() {
    Document dwg = acad.DocumentManager.MdiActiveDocument;
    Database TargetDb = dwg.Database;
    Editor ed = dwg.Editor;
    DateTime start = DateTime.Now;

    ObjectId lastId = Autodesk.AutoCAD.Internal.Utils.EntLast();

    if (lastId != ObjectId.Null) {
        long amount = 0;

        using (Transaction t = TargetDb.TransactionManager.StartTransaction()) {
            BlockTable bt = (BlockTable) t.GetObject(TargetDb.BlockTableId, OpenMode.ForRead);

            for (Int64 i = (Int64) bt.ObjectId.OldIdPtr; i <= (Int64) lastId.OldIdPtr; ++i) {
                IntPtr ptr = new IntPtr(i);
                ObjectId id = new ObjectId(ptr);
                if (id.IsValid)
                    ++amount;
            }
        }
        TimeSpan len = DateTime.Now - start;
        ed.WriteMessage(string.Format("Amount: {0}\nFast iteration time: {1} min. {2} sec.\n",
            amount, len.Minutes, len.Seconds));
    }
    else
        ed.WriteMessage("No objects in drawing.\n");
}

result:
Quote from: AutoCAD 2009
Command: KaefersIteration
Amount: 0
Fast iteration time: 0 min. 0 sec.
nothing not found. :(

kaefer

  • Guest
Re: Slow iteration on ObjectIds
« Reply #6 on: August 25, 2011, 07:10:13 AM »
nothing not found. :(

Did you add an Entity to your drawing?

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #7 on: August 25, 2011, 07:20:48 AM »
nothing not found. :(

Did you add an Entity to your drawing?
The size of a checked dwg-file is 23 Mb. It has 517 579 Entities.

kaefer

  • Guest
Re: Slow iteration on ObjectIds
« Reply #8 on: August 25, 2011, 07:22:32 AM »
Did you add another Entity to your drawing?

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #9 on: August 25, 2011, 07:24:37 AM »
Did you add another Entity to your drawing?
No, I need all database entities, not new only  :(

But if I add new Entities - it not work too.

How in your variant the code learns, with what database it is necessary to work?

Oops...
Quote
bt.ObjectId.OldIdPtr: 2 128 931 848
lastId.OldIdPtr:  2 124 488 384
second more then first.
« Last Edit: August 25, 2011, 07:38:34 AM by Andrey »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Slow iteration on ObjectIds
« Reply #10 on: August 25, 2011, 07:35:20 AM »
Are you saying that
 
(LastId - FirstId) / 8 = Total number of objects
 
Since Int64 is 8 bytes and taking the difference between first and last would be the total number bytes and dividing by eight gives total number of objects.
 
 
Code: [Select]
        [CommandMethod("FasterIteration")]
        public void FasterIteration()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor; ;
            long amount = 0;//common counter

            Int64 firstId = db.BlockTableId.OldIdPtr.ToInt64();
            Int64 lastId = Autodesk.AutoCAD.Internal.Utils.EntLast().OldIdPtr.ToInt64();

            ed.WriteMessage("\n{0} {1}\n", firstId.ToString(), lastId.ToString());

            amount = (long)((lastId - firstId) /;
            ed.WriteMessage("\n{0}\n", amount.ToString());
        }

but modifying Andreys code to output the difference between ObjectIds 98% are 8 but some will be 64, 16, 2400 etc.........
 
I guess the processor breaks it up into available areas?!???
 
Code: [Select]

        [CommandMethod("SlowIteration", CommandFlags.Modal)]
        public void SlowIteration()
        {
            Document dwg = Application.DocumentManager.MdiActiveDocument;
            Database TargetDb = dwg.Database;
            Editor ed = dwg.Editor;
            DateTime start = DateTime.Now;
            long amount = 0;//common counter
            long exceptCount = 0;//exception counter
            Int64 Current = 0;
            Int64 previous = 0;
            using (Transaction t = TargetDb.TransactionManager.StartTransaction())
            {
                for (long i = TargetDb.BlockTableId.Handle.Value; i < TargetDb.Handseed.Value; i  )
                {
                      amount;
                    ObjectId id = ObjectId.Null;
                    //Slow code begin:
                    try
                    {
                        id = TargetDb.GetObjectId(false, new Handle(i), 0);
                        previous = Current;
                        Current = id.OldIdPtr.ToInt64();
                        if (previous != 0)
                        {
                            ed.WriteMessage("\n{0}\n", (Current - previous) .ToString());
                        }
                    }
                    catch
                    {
                          exceptCount;
                        continue;
                    }
                    //Slow code end.
                }
            }
            TimeSpan len = DateTime.Now - start;
            ed.WriteMessage("\n{0}\n", exceptCount.ToString());
            ed.WriteMessage(string.Format("Amount: {0}\nSlow iteration time: {1} min. {2} sec.\n",
                amount, len.Minutes, len.Seconds));
        }

 
If it is working you could do for or while loop going backwards from the Handseed property and the first one that does not throw error set to last then break out of the loop.
 
 
 

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #11 on: August 25, 2011, 07:47:54 AM »
(LastId - FirstId) / 8 = Total number of objects
 
Since Int64 is 8 bytes and taking the difference between first and last would be the total number bytes and dividing by eight gives total number of objects.
But entity can be removed, so in an expected place it can not appear the identifier... ???
P.S. You not truly quote my code (increments have disappeared).

kaefer

  • Guest
Re: Slow iteration on ObjectIds
« Reply #12 on: August 25, 2011, 07:50:41 AM »
Int64 is 8 bytes

You've got me there. Andrey got me with another unwarranted assumption: That (entlast) after creating a new object returns a new ObjectId whose pointer is bigger than other existing pointers.

How well-founded are the assumptions that
1) BlockTable is the "first" object in the drawing, because it has Handle "1"
2) Handseed is after the "last" object in the drawing (well, it's settable).

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Slow iteration on ObjectIds
« Reply #13 on: August 25, 2011, 07:57:46 AM »
1) BlockTable is the "first" object in the drawing, because it has Handle "1"
It is not always true. I've seen dwg-file with Handle of BlockTable such as "FEDCBA", but it's handle really was "first" in dwg

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #14 on: August 25, 2011, 08:01:47 AM »
You've got me there. Andrey got me with another unwarranted assumption: That (entlast) after creating a new object returns a new ObjectId whose pointer is bigger than other existing pointers.
Online-translator translates it not clearly. I haven't understood that sense that you have written. :(

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #15 on: August 25, 2011, 09:26:34 AM »
Code: [Select]
//Database's ObjectIds iteration
[CommandMethod("FastIteration", CommandFlags.Modal)]
public void FastIteration() {
    Document dwg = acad.DocumentManager.MdiActiveDocument;
    Database TargetDb = dwg.Database;
    Editor ed = dwg.Editor;
    DateTime start = DateTime.Now;

    long amount = 0;//Database's ObjectIds common counter

    using (Transaction t = TargetDb.TransactionManager.StartTransaction()) {
        for (long i = TargetDb.BlockTableId.Handle.Value; i < TargetDb.Handseed.Value; i++) {
            ObjectId id = ObjectId.Null;

            //next line - Fatal error!!!
            int x = getAcDbObjectId17(TargetDb.UnmanagedObject, ref id, false, new Handle(i), 0);
            if (x != 0 && id.IsValid)
                ++amount;
        }
    }
    TimeSpan len = DateTime.Now - start;
    ed.WriteMessage(string.Format("Amount: {0}\nFast iteration time: {1} min. {2} sec.\n",
        amount, len.Minutes, len.Seconds));
}

//P/Invoke method for AutoCAD 2009 x86 (Alexander Rivilis's code)
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acdb17.dll", CallingConvention = CallingConvention.ThisCall,
   EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QAE?AW4ErrorStatus@Acad@@AAVAcDbObjectId@@_NABVAcDbHandle@@K@Z")]
extern static int getAcDbObjectId17(IntPtr db, ref ObjectId id, bool createnew, Handle h, Int32 reserved);

I get fatall error :(

About my topic:

I have some methods, which operation I want to accelerate. Here one of them:

Code: [Select]
public Dictionary<Type, List<ObjectId>> GetByTypes(Func<Transaction, ObjectId, bool> requirement) {
    Dictionary<Type, List<ObjectId>> dict = new Dictionary<Type, List<ObjectId>>();
    using (Transaction t = TargetDb.TransactionManager.StartTransaction()) {
        for (long i = TargetDb.BlockTableId.Handle.Value; i < TargetDb.Handseed.Value; i++) {
            ObjectId id = ObjectId.Null;
            try {
                id = TargetDb.GetObjectId(false, new Handle(i), 0);
            }
            catch { continue; }

            if (id != ObjectId.Null &&  id.IsValid && !id.IsErased && requirement(t, id)) {
                Type type = t.GetObject(id, OpenMode.ForRead).GetType();
                if (!dict.Keys.Contains(type))
                    dict.Add(type, new List<ObjectId>());
                dict[type].Add(id);
            }
        }
    }
    return dict;
}

It method return ObjectIds, grouped on Type, which is key of dictionary record.

Somebody can help with P/Invoke?

 :-(


Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #16 on: August 25, 2011, 10:18:05 AM »
Problem is solved!

Code: [Select]
//WARNING: P/Invoke method FOR AUTOCAD 2009 x86 ONLY!!! (Alexander Rivilis's code)
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acdb17.dll", CallingConvention = CallingConvention.ThisCall,
   EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QAE?AW4ErrorStatus@Acad@@AAVAcDbObjectId@@_NABVAcDbHandle@@K@Z")]
extern static int getAcDbObjectId17(IntPtr db, ref ObjectId id, bool createnew, ref Handle h, Int32 reserved);
// Define Command "AsdkCmd1"
[CommandMethod("AsdkCmd1")]
static public void test() // This method can have any name
{
    // Put your command code here
    Database db = HostApplicationServices.WorkingDatabase;
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
    DateTime start = DateTime.Now;

    long amount = 0;//common counter

    using (Transaction t = db.TransactionManager.StartTransaction()) {
        ObjectId id = new ObjectId();
        for (long i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++) {
            Handle h = new Handle(i);
            if (getAcDbObjectId17(db.UnmanagedObject, ref id, false, ref h, 0) == 0) {
                ++amount;
                id = db.GetObjectId(false, new Handle(i), 0);
                DBObject dbo= t.GetObject(id, OpenMode.ForRead);
            }
        }
    }
    TimeSpan len = DateTime.Now - start;
    ed.WriteMessage(string.Format("Amount: {0}\nFast iteration time: {1} min. {2} sec.\n",
        amount, len.Minutes, len.Seconds));

}
for other AutoCAD versions:
Code: [Select]
//Ниже приведён набор методов, с помощью которых можно получить значение идентификатора, минуя при этом генерацию
//исключения, если запрашиваемый идентификатор отсутствует в базе данных чертежа (это существенно ускоряет
//производительность)
//Низкий поклон Александру Ривилису, написавшему эти методы!!!!!
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acdb17.dll", CallingConvention = CallingConvention.ThisCall,
   EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QAE?AW4ErrorStatus@Acad@@AAVAcDbObjectId@@_NABVAcDbHandle@@K@Z")]
extern static int getAcDbObjectId17x32(IntPtr db, ref ObjectId id, bool createnew, ref Handle h, Int32 reserved);

[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acdb17.dll", CallingConvention = CallingConvention.ThisCall,
  EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QEAA?AW4ErrorStatus@Acad@@AEAVAcDbObjectId@@_NAEBVAcDbHandle@@K@Z")]
extern static int getAcDbObjectId17x64(IntPtr db, ref ObjectId id, bool createnew, ref Handle h, Int32 reserved);

[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acdb18.dll", CallingConvention = CallingConvention.ThisCall,
   EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QAE?AW4ErrorStatus@Acad@@AAVAcDbObjectId@@_NABVAcDbHandle@@K@Z")]
extern static int getAcDbObjectId18x32(IntPtr db, ref ObjectId id, bool createnew, ref Handle h, Int32 reserved);

[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acdb18.dll", CallingConvention = CallingConvention.ThisCall,
  EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QEAA?AW4ErrorStatus@Acad@@AEAVAcDbObjectId@@_NAEBVAcDbHandle@@K@Z")]
extern static int getAcDbObjectId18x64(IntPtr db, ref ObjectId id, bool createnew, ref Handle h, Int32 reserved);

public static int getAcDbObjectId(IntPtr db, ref ObjectId id, bool createnew, ref Handle h, Int32 reserved) {
    switch (Application.Version.Major) {
        case 17: {
                if (IntPtr.Size == 4) return getAcDbObjectId17x32(db, ref id, createnew, ref h, reserved);
                else return getAcDbObjectId17x64(db, ref id, createnew, ref h, reserved);
            }
        case 18: {
                if (IntPtr.Size == 4) return getAcDbObjectId18x32(db, ref id, createnew, ref h, reserved);
                else return getAcDbObjectId18x64(db, ref id, createnew, ref h, reserved);
            }
    }
    return -1;
}

Thank you all, and Alexander Rivilis!!!
« Last Edit: August 25, 2011, 11:07:21 AM by Andrey »

kaefer

  • Guest
Re: Slow iteration on ObjectIds
« Reply #17 on: August 25, 2011, 01:20:19 PM »
Code: [Select]
           if (getAcDbObjectId17(db.UnmanagedObject, ref id, false, ref h, 0) == 0) {
                ++amount;
                id = db.GetObjectId(false, new Handle(i), 0);  // <- Could you dump this line?

Firstly, congratulations!

What caught my attention now was the fact that you're doing the same thing twice, via p/invoke and for good measure the .NET way too. If I'm not completely mistaken; the second argument is actually out, and the fourth is ref. Not sure if this distinction carries over into C++ land.
Quote
Acad::ErrorStatus getAcDbObjectId(
    AcDbObjectId& retId,
    bool createIfNotFound,
    const AcDbHandle& objHandle,
    Adesk::UInt32 xRefId = 0
);


Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #18 on: August 25, 2011, 01:26:57 PM »
What caught my attention now was the fact that you're doing the same thing twice
Yes it my mistake. :) Thank you!

I have published the code and tests here (the text in Russian, but the code it is possible to read and understand).
« Last Edit: August 25, 2011, 01:32:50 PM by Andrey »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Slow iteration on ObjectIds
« Reply #19 on: August 25, 2011, 01:45:07 PM »
One thing that might help instead of storing types you could use strings and not have to open each object.
 
For example this just prints all the
ObjectId's in modelSpace ObjectID.ObjectClass.Name & ObjectID.ObjectClass.DxfName
 
For a line will print
Quote
AcDbLine LINE

Code: [Select]

              [CommandMethod("PrintAllModelSpaceTypes")]
        public void PrintAllModelSpaceTypes()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction trx = db.TransactionManager.StartTransaction())
            {
               
                    BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
                    BlockTableRecord modelBtr = (BlockTableRecord)trx.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                    foreach (ObjectId objId in modelBtr)
                    {               
                            ed.WriteMessage("\n{0} {1}", objId.ObjectClass.Name, objId.ObjectClass.DxfName);                       
                    }
                    trx.Commit();
                             
            }
        }
« Last Edit: August 25, 2011, 01:50:25 PM by Jeff H »

kaefer

  • Guest
Re: Slow iteration on ObjectIds
« Reply #20 on: August 26, 2011, 02:16:58 AM »
One thing that might help instead of storing types you could use strings and not have to open each object.

It does help indeed. For the benefit of those being on a platform slightly more up-to-date then there's another thing that helps: Database.TryGetObjectId. Fast it is too.

Code: [Select]
        [CommandMethod("Test")]
        static public void test()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
            long amount = 0;
            Dictionary<string, int> d = new Dictionary<string, int>();
            ObjectId id = ObjectId.Null;
            for (long i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++)
            {
                Handle h = new Handle(i);
                if (db.TryGetObjectId(h, out id) && !id.IsNull && id.IsValid && !id.IsErased)
                    {
                        string t = id.ObjectClass.DxfName;
                        amount++;       
                        if(d.ContainsKey(t))
                            d[t]++;
                        else
                            d.Add(t, 1);
                    }
            }
            sw.Stop();
            foreach(KeyValuePair<string,int> kvp in d)
                ed.WriteMessage("\n{0}: {1} ", kvp.Key, kvp.Value);
            ed.WriteMessage("\nTotal {0} objects in drawing, time elapsed: {1} ", amount, sw.Elapsed);
        }

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #21 on: August 26, 2011, 02:41:09 AM »
db.TryGetObjectId(h, out id)
You are magician!!!! Many thanks!!!!! It is the fastest variant, fastest all previous!!! (3 seconds).

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Slow iteration on ObjectIds
« Reply #22 on: August 26, 2011, 04:03:51 AM »
One thing that might help instead of storing types you could use strings and not have to open each object.
Thank you! It really very much has accelerated operation.