Author Topic: Are Data inside Xrecord really Disposed ?  (Read 2707 times)

0 Members and 1 Guest are viewing this topic.

bikelink

  • Guest
Are Data inside Xrecord really Disposed ?
« on: March 24, 2010, 04:30:21 AM »
This is a snippet of my code used to remove an Xrecord
I loop also an add Xrecord (same dictionary ecc..) and i've tried to force a GC.Collect after this but the system memory increased
Why the memory increased ? after the first Add i supposed it's remain constants (first delete --> after add )
Code: [Select]
// The Main loop is
 for (int k = 0; k < 100000; k++)
                {
                    SetDATAXRecord(mydocument, mydataset);
                }


void SetDATAXRecord(Document d, Dataset ds)
{
// the first time this skip and return..
            b2XRec.deleteEntryXRecordFromDictionary("mydictname", "mylabel");
// add xrecord...
            b2XRec.setDatasetInXrecord(ds, "mydictname", "mylabel");
            GC.Collect();
}


public static bool deleteEntryXRecordFromDictionary(string dictionaryName, string nameEntry)
            {
                ObjectId idremoved = ObjectId.Null;

                DBDictionary mioDizionario = null;
                using (DocumentLock docLock = m_document.LockDocument())
                {
                    SetDbFromDocument();
                    using (Transaction trans = db.TransactionManager.StartTransaction())
                    {
                        try
                        {
                            // First, get the NOD...
                            using (DBDictionary dict = (DBDictionary)trans.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForWrite))
                            {
                                if (dict.Contains(dictionaryName))
                                {
                                    ObjectId idXrecDict = dict.GetAt(dictionaryName);
                                    mioDizionario = (DBDictionary)trans.GetObject(idXrecDict, OpenMode.ForWrite);


                                    if (mioDizionario.Contains(nameEntry))
                                    {
                                        idremoved = mioDizionario.Remove(nameEntry);
                                        using (Xrecord pEnt = (Xrecord)trans.GetObject(idremoved, OpenMode.ForWrite, false, true))
                                        {
                                            pEnt.Erase();
                                        }
                                    }
                                    mioDizionario.Erase();
                                    // mioDizionario.ReleaseExtensionDictionary();
                                    trans.Commit();
                                    
                                }
                            }
                        }
                        catch (Autodesk.AutoCAD.Runtime.Exception e)
                        {
                            MessageBox.Show(e.Message);
                            trans.Abort();
                            return false;
                        }
                    }
                }
                return (idremoved != ObjectId.Null);
            }


[edit: codetags added]
« Last Edit: March 24, 2010, 06:56:46 AM by Kerry Brown »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Are Data inside Xrecord really Disposed ?
« Reply #1 on: March 24, 2010, 04:46:33 AM »
Typically, calling erase does not remove the dbobject from the database, or from memory.
Also, sometimes, dangling ResultBuffers will be cleaned up by the finalizer (shutting down Acad) :-)

bikelink

  • Guest
Re: Are Data inside Xrecord really Disposed ?
« Reply #2 on: March 24, 2010, 05:02:45 AM »
Thanks Daniel!
wouldn't be the garbage collector to set free the memory disposed?
If I use resultbuffer...and I disposed it, I  guess that GC.Collect could be reset the memory. isn't it ?
I don't know understood  the real life cicle of my resultbuffer...and how can i be really Sure to free memory.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Are Data inside Xrecord really Disposed ?
« Reply #3 on: March 24, 2010, 05:26:52 AM »
if you explicitly call dispose on a Resultbuffer, it will delete the underlying resbuf, else the finalizer will pick it up. calling GC, will not produce consistent results.

Back to your Xrecord, I think you can set the Resultbuffer property with an empty buffer and it will clear the existing data.


It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Are Data inside Xrecord really Disposed ?
« Reply #4 on: March 24, 2010, 06:16:48 AM »
You can test it with the routine (attached here) I wrote for storing files in a dwg

(AcIoPutFile "c:\\MySQLite.db" "StoredFiles" "MySQLite" nil)
do a save, note the dwg size
(AcIoClearFile "StoredFiles" "MySQLite")
do a save, note the dwg size

replace MySQLite with your info,
for reference http://www.theswamp.org/index.php?topic=26687.0

bikelink

  • Guest
Re: Are Data inside Xrecord really Disposed ?
« Reply #5 on: March 24, 2010, 06:27:07 AM »
quick update... : :realmad:
Code: [Select]

try
{
for (int k = 0; k < 100000; k++)
                {
                    ArredilUtil.SaveDs(mydoc, mydataset);
                    //GC.Collect();
                    System.Diagnostics.Debug.WriteLine(GC.GetTotalMemory(false));
                    System.Diagnostics.Debug.WriteLine(k);
                    
                }
}
catch (System.Runtime.InteropServices.SEHException ex)  :pissed:
            {  
                System.Windows.Forms.MessageBox.Show(ex.Message + ex.TargetSite.Name);
            }



// the output produced is
4696 (number of loops)
7286352 (memory)
4697
8203952
4698
10369092
4699

and I see the problem in
"AcDbXrecord.setFromRbChain"


so with your suggest i have added this row in xrecord deleted method :

Code: [Select]
using (Xrecord pEnt = (Xrecord)trans.GetObject(idremoved, OpenMode.ForWrite, false, true))
 {
       [b][color=red]pEnt.Data = new ResultBuffer();[/color][/b]
      pEnt.Erase();
                      
 }
and the result seems .. SUCCESS!!!!!!!!!!!!!!!

I though that to be disposed the Data / resultbuffer  should be cleaned but set to new resultbuffer isn't remove the real existed data.
So we add a new pointer (with empty data) but I didn't understood how the old data are removed.
If i don't "free" or remove thre previous pointer/structure i can't imagine how autocad can be remove it..
I guess that  the assignment with overload = remove the old data and if the resultbuffer is empty it is really free for the garbage collector.
In my opinion the data in Xrecord should be removed when i delete the parent (xrecord) without concern about his members.


Daniel i want to said Thank You very much for your suggest!


[edit: codetags added]
« Last Edit: March 24, 2010, 06:55:12 AM by Kerry Brown »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Are Data inside Xrecord really Disposed ?
« Reply #6 on: March 24, 2010, 06:36:06 AM »
glad you got it  8-)