TheSwamp
Code Red => .NET => Topic started by: bikelink 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 )
// 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]
-
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) :-)
-
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.
-
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.
-
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
-
quick update... : :realmad:
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 :
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]
-
glad you got it 8-)