.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

WblockCloneObjects memory consumption

12 REPLIES 12
Reply
Message 1 of 13
E3DE
1170 Views, 12 Replies

WblockCloneObjects memory consumption

Hi,

i need to read an external dwg and import only some entities.

I use WblockCloneObjects, it work fine but i found a memory problem, the memory is not disposed

ad if i watch the resource manager autocad memory process significantly increases after WblockCloneObjects.

 

Where is the problem?

 

Thank you very much.

 

This is my test code, and i attach my sample dwg.

 

[CommandMethod("TestClone", CommandFlags.Transparent)]
        public void TestClone()
        {
            // repeated 20 times to highlight the memory consumption
            for (int i = 0; i < 20; i++)
            {
                ObjectIdCollection filteredIds = new ObjectIdCollection();

                Database targetDb = ACAP.Application.DocumentManager.MdiActiveDocument.Database;
                
                using (Transaction trMain = targetDb.TransactionManager.StartTransaction())
                {
                    using (Database db = new Database(false, true))
                    {
                        // read the source dwg
                        db.ReadDwgFile(@"D:\he10t.dwg", FileOpenMode.OpenForReadAndAllShare, true, "");
                        
                        // get all entities
                        using (Transaction trSource = db.TransactionManager.StartTransaction())
                        {
                            BlockTable pBT = (BlockTable)trSource.GetObject(db.BlockTableId, OpenMode.ForRead, false);
                            BlockTableRecord pBTR = (BlockTableRecord)trSource.GetObject(pBT[BlockTableRecord.ModelSpace], OpenMode.ForRead, false);

                            foreach (ObjectId id in pBTR)
                            {
                                // ...open entity and filter
                                filteredIds.Add(id);
                            }
                        }

                        // clone the filtered entities in current document
                        using (ACAP.DocumentLock dl = ACAP.Application.DocumentManager.MdiActiveDocument.LockDocument())
                        {
                            using (IdMapping mapping = new IdMapping())
                            {
                                // now clone the objects into the destdb
                                ObjectId destDbMsId = SymbolUtilityServices.GetBlockModelSpaceId(targetDb);

                                db.WblockCloneObjects(filteredIds, destDbMsId, mapping, DuplicateRecordCloning.Replace, false);
                            }
                        }
                    }
                    trMain.Commit();
                }    
                filteredIds.Dispose();
            }
            
        }

 

12 REPLIES 12
Message 2 of 13
E3DE
in reply to: E3DE

I tried both autocad 2013 and 2014, but same result, autocad memory increase and not disposed.
It's bug?
Thank you
Message 3 of 13
E3DE
in reply to: E3DE

I do some tests.
I try to use c++ project to reproduce the problem, to understand if the problem is in the .net api wrapper or native objectarx.
I use ArxDbg sample, command  testWblockCloneObjects and i have same problem,
but i observe that memory increases significantly only when use flag DuplicateRecordCloning.Replace parameter in WBlockCloneObject while if i use DuplicateRecordCloning.Ignore memory increases more slowly.

 

No one has encountered this problem?

 

Thank you very much.

Message 4 of 13
owenwengerd
in reply to: E3DE

It sounds like the cloning operation is working as designed. If you need to control the lifetime of the memory consumed by database operations, you can use side databases (i.e. database objects that you create and whose lifetimes you control). All database memory will be freed when the database is destroyed.

--
Owen Wengerd
ManuSoft
Message 5 of 13
E3DE
in reply to: owenwengerd

Hi,

thank you for your answer.

I do test with a side database, and repeat the clone for 200 times, memory is allocated (150mb with replace flag and 15mb with ignore flag) and not disposed after side database was destroyed, not even closing all autocad documents. In my opinion this is not normal, specially with replace parameter.

 

Thank you for help.

 

This is my test code:

 

 

[CommandMethod("TestCloneResetDb", CommandFlags.Session)]
        public void TestCloneResetDb()
        {
            if (testCloneDb != null)
            {
                testCloneDb.Clone();
                testCloneDb = null;
            }
        }

        [CommandMethod("TestClone", CommandFlags.Session)]
        public void TestClone()
        {
            try
            {
                if (testCloneDb == null)
                    testCloneDb = new Database(true, true);

                using (DocumentLock acLckDoc = ACAP.Application.DocumentManager.MdiActiveDocument.LockDocument())
                {
                    using (Transaction trDest = ACAP.Application.DocumentManager.MdiActiveDocument.TransactionManager.StartTransaction())
                    {
                        // repeated 20 times to highlight the memory consumption
                        for (int i = 0; i < 200; i++)
                        {
                            ObjectIdCollection filteredIds = new ObjectIdCollection();

                            Database db = new Database(false, true);

                            // read the source dwg
                            db.ReadDwgFile(@"D:\he10t.dwg", FileOpenMode.OpenForReadAndReadShare, true, "");

                            // get all entities
                            using (Transaction trSource = db.TransactionManager.StartTransaction())
                            {
                                BlockTable pBT = (BlockTable)trSource.GetObject(db.BlockTableId, OpenMode.ForRead, false);
                                BlockTableRecord pBTR = (BlockTableRecord)trSource.GetObject(pBT[BlockTableRecord.ModelSpace], OpenMode.ForRead, false);

                                foreach (ObjectId id in pBTR)
                                {
                                    // ...open entity and filter
                                    filteredIds.Add(id);
                                }

                                pBTR.Dispose();
                                pBT.Dispose();
                            }

                            IdMapping mapping = new IdMapping();

                            // now clone the objects into the destdb
                            ObjectId destDbMsId = SymbolUtilityServices.GetBlockModelSpaceId(testCloneDb);

                            db.WblockCloneObjects(filteredIds, destDbMsId, mapping, DuplicateRecordCloning.Replace, false);

                            db.Dispose();

                            filteredIds.Dispose();
                        }
                        trDest.Commit();
                    }
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

 

Message 6 of 13
E3DE
in reply to: E3DE

I forgot, the memory is released when autocad is closed.
Message 7 of 13
owenwengerd
in reply to: E3DE

I suspect you are mistaken about whether memory is still in use after your database is disposed. Note that memory can be allocated from the OS perspective even though it is free to use by the application. If you are observing allocated memory with something like task manager, then you are not getting an accurate picture of AutoCAD memory usage.

--
Owen Wengerd
ManuSoft
Message 8 of 13
SENL1362
in reply to: owenwengerd

What is a an accurate method to find out the memory usage of (parts of) the programs?
We noticed the same problems when importing DXF using VBA+.NET in AutoCAD 2012. The results are out of memory in 32 bits systems, thus regularly restart AutoCAD to get the the memory back.
Never found a real solution for the problem other than to upgrade to AutoCAD 2014 on 64 bits enable us to add more RAM.
So what is a good method to monitor monitor consumption and prevent memory leaks.
Message 9 of 13
E3DE
in reply to: owenwengerd

Hi,

I make an error, if i dispose side database memory are disposed correctly.

Anyway in real world application i use active document database not side database, and memory are free only when aurocad is closed.

There is a way to clear unused memory from a database without disposing it?

 

Thank you very much.

 

Message 10 of 13
owenwengerd
in reply to: E3DE

Memory usage in AutoCAD is a big topic; too big for me to tackle here. Due to memory fragmentation, it is possible for AutoCAD to eventually exhaust all available memory. Over time, fragmentation occurs from the cycle of memory blocks being allocated, used, then freed. For this reason, even processes that free all memory they allocate, can eventually result in no large blocks of memory being available for use. It is well established that batch processes should (and must, if they are to be robust), periodically close the AutoCAD process and restart fresh.

--
Owen Wengerd
ManuSoft
Message 11 of 13
SENL1362
in reply to: owenwengerd

That's exactly what we experiences, freed memory not reclaimable until the Applicaton closed.
However regarding the batch processing i can remember the time we used 4 AutoCAD session simultaneously to convert more than 100000 drawings without any crash or memory problems. But i have to admit Windows was the real Windows NT and AutoCAD did just CAD :).

Message 12 of 13
autodaug
in reply to: owenwengerd

That says it pretty well: it's a big topic. Some complicating factors include:

  1. Different ways to measure memory use: committed, reserved, working set, heap, etc. The task manager tends to show "private working set", but it has changed how it reports memory use over the releases
  2. Various acad subsystems: database, graphics, .NET, solids/shape manager, web browser, other plug-ins, etc, which may have their own memory usage behavior
  3. Acad databases hold on to erased objects until the database is deleted, in case the objects need to be un-erased
  4. Heaps hold on to freed memory, for later reallocation and because of fragmentation
  5. Acad's heap libraries (internal and external) and usage patterns have changed over the releases
  6. Windows and MSVC heap implementations have changed over the releases
  7. 32-bit processes are of course much more restricted. And 32-bit Windows systems can't handle as much physical RAM as 64-bit Windows

Regarding #3, fwiw, there is an API for telling a database to release its erased objects' memory. But I think it's better to use side databases and delete the entire database instead, if possible.

 

http://through-the-interface.typepad.com/through_the_interface/2008/11/reclaiming-memo.html

 

http://adndevblog.typepad.com/autocad/2012/04/reclaiming-memory-of-erased-objects.html

 

 

 

 

 

 

 

 

Message 13 of 13
E3DE
in reply to: autodaug

Thank you all for your help.

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost