database free the memory

database free the memory

Anonymous
Not applicable
1,719 Views
13 Replies
Message 1 of 14

database free the memory

Anonymous
Not applicable

how to  free the memory  with ReclaimMemoryFromErasedObjects ?   I try to  load file  then    delete all objects  ,  But  I find  the memoey  increase more and more?  what's wrong?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.Gis.Map.Platform.Utils;

namespace ReclaimMemory
{
    public class Class1
    {
        [CommandMethod("hello")]
        public void hello()
        {
            Util.PrintLn("com to  hello");
        }
        [CommandMethod("MyMemory")]
        public void myMemory()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database destDb = Application.DocumentManager.MdiActiveDocument.Database;
            for (int i = 0; i < 50; i++)
            {
                string filename = "C:\\110344.dwg";
                Util.PrintLn("file"+i);
                Database sourceDb = new Database(false, true);
                sourceDb.ReadDwgFile(filename, System.IO.FileShare.Read, false, null);
                var SourceObjectIds = new ObjectIdCollection();
                Autodesk.AutoCAD.DatabaseServices.TransactionManager SourceTm = sourceDb.TransactionManager;
                using (Transaction trans = destDb.TransactionManager.StartTransaction())
                {
                    try
                    {
                        var blockTable = (BlockTable)trans.GetObject(destDb.BlockTableId, OpenMode.ForRead);
                        using (Transaction extTrans = sourceDb.TransactionManager.StartTransaction())
                        {
                            dynamic extBlockTable = (BlockTable)extTrans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                            dynamic extModelSpace = (BlockTableRecord)extTrans.GetObject(extBlockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                            foreach (ObjectId id in extModelSpace)
                            {
                                SourceObjectIds.Add(id);
                            }

                        }
                        sourceDb.CloseInput(true);
                        dynamic idmapping = new IdMapping();
                        // destDb.WblockCloneObjects(SourceObjectIds, destDb.BlockTableId, idmapping, DuplicateRecordCloning.Replace, false);
                        destDb.WblockCloneObjects(SourceObjectIds, blockTable[BlockTableRecord.ModelSpace], idmapping, DuplicateRecordCloning.Ignore, false);
                        trans.Commit();
                    }
                    catch (System.Exception ex)
                    {

                        Util.PrintLn(ex.Message);

                    }
                }
                string saveFile ="C:\\"+ i + ".dwg";
                destDb.SaveAs(saveFile, true, DwgVersion.AC1800, null);

                //**************delete objects  and  free  memory

                using (ObjectIdCollection erased = new ObjectIdCollection())
                {
                    using (Transaction trans = destDb.TransactionManager.StartTransaction())
                    {

                        BlockTable bt = (BlockTable)trans.GetObject(destDb.BlockTableId, OpenMode.ForWrite);
                        foreach (ObjectId btrid in bt)
                        {
                            BlockTableRecord btr = (BlockTableRecord)trans.GetObject(btrid, OpenMode.ForWrite);
                            foreach (ObjectId eid in btr)
                            {
                                Entity ent = trans.GetObject(eid, OpenMode.ForWrite) as Entity;
                                if (ent != null)
                                {
                                    ent.Erase(true);
                                    erased.Add(eid);
                                }


                            }
                        }

                        trans.Commit();

                    }
                    destDb.ReclaimMemoryFromErasedObjects(erased);
                    erased.Clear();
                }


            }

        }
    }
}
0 Likes
Accepted solutions (1)
1,720 Views
13 Replies
Replies (13)
Message 2 of 14

ActivistInvestor
Mentor
Mentor

@Anonymous wrote:

how to  free the memory  with ReclaimMemoryFromErasedObjects ?   I try to  load file  then    delete all objects  ,  But  I find  the memoey  increase more and more?  what's wrong?


It's hard to tell what's wrong without testing your code, but I would suggest reading the native API docs for reclaimMemoryFromErasedObjects(), because it goes into much greater detail than the managed API docs.

0 Likes
Message 3 of 14

Anonymous
Not applicable

i find  the memory  begin to be  free , when  all  the  50 files work finish...

i  want  to  that  when  one  file  finish work ,the memory  begin  to free  immediately,so  the  max  memory  overhead is  not so large

so  the   "ReclaimMemoryFromErasedObjects"  is not  usefull  for  me ?

0 Likes
Message 4 of 14

_gile
Consultant
Consultant

Hi,

 

Just a shoot in the dark, not tested with a big amount of files.

What if you call Dispose() on the newly created Database, or, better wrap int in a using statement:

 

using(Database sourceDb = new Database(false, true))
{
// use sourceDb
} // sourceDb is disposed here and can be garbage collected

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 14

Anonymous
Not applicable

i  change  code like this 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.Gis.Map.Platform.Utils;

namespace ReclaimMemory
{
    public class Class1
    {
        [CommandMethod("hello")]
        public void hello()
        {
            Util.PrintLn("com to  hello");
        }
        [CommandMethod("MyMemory")]
        public void myMemory()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database destDb = Application.DocumentManager.MdiActiveDocument.Database;
            for (int i = 0; i < 50; i++)
            {
                string filename = "C:\\110344.dwg";
                Util.PrintLn("file"+i);
                Database sourceDb = new Database(false, true);
                sourceDb.ReadDwgFile(filename, System.IO.FileShare.Read, false, null);
                var SourceObjectIds = new ObjectIdCollection();
                Autodesk.AutoCAD.DatabaseServices.TransactionManager SourceTm = sourceDb.TransactionManager;
                using (Transaction trans = destDb.TransactionManager.StartTransaction())
                {
                    try
                    {
                        var blockTable = (BlockTable)trans.GetObject(destDb.BlockTableId, OpenMode.ForRead);
                        using (Transaction extTrans = sourceDb.TransactionManager.StartTransaction())
                        {
                            dynamic extBlockTable = (BlockTable)extTrans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                            dynamic extModelSpace = (BlockTableRecord)extTrans.GetObject(extBlockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                            foreach (ObjectId id in extModelSpace)
                            {
                                SourceObjectIds.Add(id);
                            }

                        }
                        sourceDb.CloseInput(true);
                        dynamic idmapping = new IdMapping();
                        // destDb.WblockCloneObjects(SourceObjectIds, destDb.BlockTableId, idmapping, DuplicateRecordCloning.Replace, false);
                        destDb.WblockCloneObjects(SourceObjectIds, blockTable[BlockTableRecord.ModelSpace], idmapping, DuplicateRecordCloning.Ignore, false);
                        trans.Commit();
//**************add dispose()
sourceDb.Dispose();
SourceObjectIds.Dispose(); } catch (System.Exception ex) { Util.PrintLn(ex.Message); } } string saveFile ="C:\\"+ i + ".dwg"; destDb.SaveAs(saveFile, true, DwgVersion.AC1800, null); //**************delete objects and free memory using (ObjectIdCollection erased = new ObjectIdCollection()) { using (Transaction trans = destDb.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)trans.GetObject(destDb.BlockTableId, OpenMode.ForWrite); foreach (ObjectId btrid in bt) { BlockTableRecord btr = (BlockTableRecord)trans.GetObject(btrid, OpenMode.ForWrite); foreach (ObjectId eid in btr) { Entity ent = trans.GetObject(eid, OpenMode.ForWrite) as Entity; if (ent != null) { ent.Erase(true); erased.Add(eid); } } } trans.Commit(); } destDb.ReclaimMemoryFromErasedObjects(erased);

//********* add dispose()
destDb.Dispose();
erased.Clear();
} } } } }

  dispose  function  seem  to be unuseful  .

  the file  of "C:\\110334.dwg"  is  1.9MB , in the  working  processing , The most  memory overhead  of acad.exe   is more than  3G !

 when all  the work  finish ,  the acad.exe  memory  overhead  reduce to about  900M 

  

 

0 Likes
Message 6 of 14

_gile
Consultant
Consultant

Looking more attentively to your code, it seems to me it needs some algorithmic and coding optimisation.

 

You do not need to create 50 side databases to get get everytime the same ObjectIdCollection.

You should create 50 side databases to create the new dwg files.

You should not use the dynamic type for strongly typed objects (use the type or var keyword instead).

 

Try something like this.

 

        [CommandMethod("MyMemory")]
        public void myMemory()
        {
            // Get the source ObjectIds from sourceDb only once
            var sourceObjectIds = new ObjectIdCollection();
            string filename = "C:\\110344.dwg";
            using (Database sourceDb = new Database(false, true))
            {
                sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);
                using (Transaction extTrans = sourceDb.TransactionManager.StartOpenCloseTransaction())
                {
                    var extBlockTable = (BlockTable)extTrans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                    var extModelSpace = (BlockTableRecord)extTrans.GetObject(extBlockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                    foreach (ObjectId id in extModelSpace)
                    {
                        sourceObjectIds.Add(id);
                    }
                }
                // Loop to create the 50 new files
                for (int i = 0; i < 50; i++)
                {
                    Util.PrintLn("file" + i);
                    string saveFile = "C:\\" + i + ".dwg";
                    using (var destDb = new Database(true, true))
                    {
                        var mapping = new IdMapping();
                        sourceDb.WblockCloneObjects(
                            sourceObjectIds, 
                            SymbolUtilityServices.GetBlockModelSpaceId(destDb), 
                            mapping, 
                            DuplicateRecordCloning.Ignore, 
                            false);
                        destDb.SaveAs(saveFile, true, DwgVersion.AC1800, null);
                    }
                }
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 14

Anonymous
Not applicable

thank  you for reply!

oh~~~~ as  your code ,maybe  much better.

Actually, very time  the  file  loaded   is different,  it  just  a  test , so  i  get  the  same  file  

Actually,I have more  than 50 different  files ,then  operate the  file  ,then  save  and  close, one by one 

can you understand  what i mean?

0 Likes
Message 8 of 14

_gile
Consultant
Consultant

Sorry I cannot understand what you're trying to do.

The code I purposed is an optimisation of the one you posted (creating 50 new files with the content of the sourceDB model space). If this does not reflect what you're trying to achieve, why do you use it as testing code ?

 

So please, just try to clearly explain what you want you to so that we're not shooting in the dark...



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 9 of 14

Anonymous
Not applicable

i am sorry ,  My  English  is poor 

the  actual   code    like  this 


using System.Linq; using System.Text; using System.Threading.Tasks; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.Gis.Map.Platform.Utils; namespace ReclaimMemory { public class Class1 { [CommandMethod("hello")] public void hello() { Util.PrintLn("com to hello"); } [CommandMethod("MyMemory")] public void myMemory() { Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database destDb = Application.DocumentManager.MdiActiveDocument.Database; for (int i = 0; i < 50; i++) { //string filename = "C:\\110344.dwg"; string filename = "C:\\110344"+i+".dwg"; Util.PrintLn("file"+i); Database sourceDb = new Database(false, true); sourceDb.ReadDwgFile(filename, System.IO.FileShare.Read, false, null); var SourceObjectIds = new ObjectIdCollection(); Autodesk.AutoCAD.DatabaseServices.TransactionManager SourceTm = sourceDb.TransactionManager; using (Transaction trans = destDb.TransactionManager.StartTransaction()) { try { var blockTable = (BlockTable)trans.GetObject(destDb.BlockTableId, OpenMode.ForRead); using (Transaction extTrans = sourceDb.TransactionManager.StartTransaction()) { dynamic extBlockTable = (BlockTable)extTrans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead); dynamic extModelSpace = (BlockTableRecord)extTrans.GetObject(extBlockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead); foreach (ObjectId id in extModelSpace) { SourceObjectIds.Add(id); } } sourceDb.CloseInput(true); dynamic idmapping = new IdMapping(); // destDb.WblockCloneObjects(SourceObjectIds, destDb.BlockTableId, idmapping, DuplicateRecordCloning.Replace, false); destDb.WblockCloneObjects(SourceObjectIds, blockTable[BlockTableRecord.ModelSpace], idmapping, DuplicateRecordCloning.Ignore, false); trans.Commit(); } catch (System.Exception ex) { Util.PrintLn(ex.Message); } } string saveFile ="C:\\"+ i + ".dwg"; destDb.SaveAs(saveFile, true, DwgVersion.AC1800, null); //**************delete objects and free memory using (ObjectIdCollection erased = new ObjectIdCollection()) { using (Transaction trans = destDb.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)trans.GetObject(destDb.BlockTableId, OpenMode.ForWrite); foreach (ObjectId btrid in bt) { BlockTableRecord btr = (BlockTableRecord)trans.GetObject(btrid, OpenMode.ForWrite); foreach (ObjectId eid in btr) { Entity ent = trans.GetObject(eid, OpenMode.ForWrite) as Entity; if (ent != null) { ent.Erase(true); erased.Add(eid); } } } trans.Commit(); } destDb.ReclaimMemoryFromErasedObjects(erased); erased.Clear(); } } } } }

 i  change  the code  "string   filename="C:\\110334.dwg""   to   "string  filename="c:\\110334"+i+".dwg""

every time  ,I  load  the  different  file 

0 Likes
Message 10 of 14

Juergen_Becker
Advocate
Advocate

Hi,

 

please commit all your transaction even if it is not really necessary. 

Look here: http://spiderinnet1.typepad.com/blog/2012/01/autocad-net-transaction-and-performance.html

 

When you commit it is much faster and saver.

 

Regards Jürgen

 

 

I hope my tip helps. If so then give me kudos and mark the tip as a solution.
Thanks.

Jürgen A. Becker
Building Services

Development and Support
Autodesk Forge Spezialist


CAD-Becker.de
https://www.CAD-Becker.de

0 Likes
Message 11 of 14

_gile
Consultant
Consultant
Accepted solution

Your code remains confusing (you call WblockCloneObjects on the destination database instance whith object ids from the source database).

 

If I don't misundertand, you already have 50 source files on C: drive (1103440.dwg, 1103441.dwg, ..., 11034449.dwg) and you to create 50 new files on C: (0.dwg, 1.dwg, ..., 49.dwg) and copying the contents of the source file model space into the new file.

 

If this is not what you want to achieve, please explain what you're trying to do in plain English (use Google transalation if needed) without showing code which does not reflect your goal.

 

If I completely understood, it looks like copying files and you can simply copy the files without using AutoCAD:

 

for (int i = 0; i < 50; i++)
{
    System.IO.File.Copy("C:\\110344" + i + ".dwg", "C:\\" + i + ".dwg");
}

If you absolutely need to make a Wbloc operation (i.e. do not copy the layouts), try the following code and overall compare it to your code to try to understand what was wrong with yours:

 

        [CommandMethod("MyMemory")]
        public void myMemory()
        {
            for (int i = 0; i < 50; i++)
            {
                string filename = "C:\\110344" + i + ".dwg";
                Util.PrintLn("file" + i);

                // get the ObjectIds form sourceDb model space
                using (Database sourceDb = new Database(false, true))
                {
                    var sourceObjectIds = new ObjectIdCollection();
                    sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);
                    using (Transaction extTrans = sourceDb.TransactionManager.StartOpenCloseTransaction())
                    {
                        var extBlockTable = (BlockTable)extTrans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                        var extModelSpace = (BlockTableRecord)extTrans.GetObject(extBlockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                        foreach (ObjectId id in extModelSpace)
                        {
                            sourceObjectIds.Add(id);
                        }
                    }

                    // create a new file and copy the objects
                    string saveFile = "C:\\" + i + ".dwg";
                    using (var destDb = new Database(true, true))
                    {
                        var mapping = new IdMapping();
                        sourceDb.WblockCloneObjects(
                            sourceObjectIds,
                            SymbolUtilityServices.GetBlockModelSpaceId(destDb),
                            mapping,
                            DuplicateRecordCloning.Ignore,
                            false);
                        destDb.SaveAs(saveFile, true, DwgVersion.AC1800, null);
                    }
                }
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 12 of 14

_gile
Consultant
Consultant

With your code (your algorithm more accurately), the memory increase because you add entities to the current database and erase them at each iteration. AutoCAD keeps all these operations in memory.

The code I purposed creates each new drawing "in memory" as side database and does nothing to the current database.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 13 of 14

Anonymous
Not applicable

greate  !   you are right!

that's  the code  i want  ,thank   you  very much!

 

Besides ,I  have a  another  quesion

you said  that " ......a Wbloc operation (i.e. do not copy the layouts)",

I absolutely need to make a Wbloc operation,  want  copy  everything  from  source  fiel  ,contain   layouts..   what  should  i do ?

0 Likes
Message 14 of 14

_gile
Consultant
Consultant

As I said upper, if you simply want to copy the whole files, you do not need to use AutoCAD.

Just create a simple Console Application with:

 

    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 50; i++)
            {
                System.IO.File.Copy("C:\\110344" + i + ".dwg", "C:\\" + i + ".dwg");
            }
        }
    }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes