Login  Register

QLXL possible memory leak revisited

Posted by Peter Caspers-2 on Apr 01, 2012; 8:13am
URL: http://quantlib.414.s1.nabble.com/QLXL-possible-memory-leak-revisited-tp9438.html

Hi Eric, Ferdinando, Luigi, all,

some months ago there were discussions about a possible memory leak in QLXL 1.1, in fact I found two related threads

http://old.nabble.com/qlxl-dependencies-and-object-updates-td30925399.html
http://old.nabble.com/possible-memory-leak-in-quantlib-addin-td29510169.html

I guess the reason for the observation of increasing memory usage when doing recalculations of excel sheets is the multiple registration of observables on the level of ObjectWrapper in the object handler. I just inserted a line that unregisters all observables before registering the precendet objects, i.e.

diff --git a/ObjectHandler/oh/repository.cpp b/ObjectHandler/oh/repository.cpp
index 49e8b76..563b4e1 100644
--- a/ObjectHandler/oh/repository.cpp
+++ b/ObjectHandler/oh/repository.cpp
@@ -109,6 +109,8 @@ namespace ObjectHandler {
     void Repository::registerObserver(
         boost::shared_ptr<ObjectWrapper> objWrapper){

+            objWrapper->unregisterAllWith();
+

             const std::set<std::string>& relationObs = objWrapper->object()->properties()->getPrecedentObjects();
             std::set<std::string>::const_iterator iter = relationObs.begin();
             for(; iter != relationObs.end();  iter++){


and thereby fixing the problem as can be tested e.g. in Ferdinandos test sheet attached to one of the old postings (book2.xls, running the macro calc_forever).

I think one can also constrain the call of registerObserver to the case of newly created ObjectWrapper instances and explicitly overwritten ones, i.e. in addition to the above change one could write

diff --git a/ObjectHandler/ohxl/repositoryxl.cpp b/ObjectHandler/ohxl/repositoryxl.cpp
index 54dbfd0..31e8d9c 100644
--- a/ObjectHandler/ohxl/repositoryxl.cpp
+++ b/ObjectHandler/ohxl/repositoryxl.cpp
@@ -79,6 +79,7 @@ namespace ObjectHandler {
                     new ObjectWrapperXL(objectID, object, callingRange));
                 objectMap_[objectID] = objectWrapperXL;
                 callingRange->registerObject(objectID, objectWrapperXL);
+                registerObserver(objectWrapperXL);
             } else {
                 objectWrapperXL = boost::static_pointer_cast<ObjectWrapperXL>(result->second);
                 if (objectWrapperXL->callerKey() != callingRange->key()) {
@@ -88,11 +89,11 @@ namespace ObjectHandler {
                         objectWrapperXL->callerAddress());
                     objectWrapperXL->resetCaller(callingRange);
                     callingRange->registerObject(objectID, objectWrapperXL);
+                    registerObserver(objectWrapperXL);
                 }
                 objectWrapperXL->reset(object);
             }
-
-            registerObserver(objectWrapperXL);


             return objectWrapperXL->idFull();
     }


and get the same result with even slightly improved efficiency.

I also noted that the observer / observable pattern code is duplicated in the object handler (objecthandler/oh/observable.hpp). In QL 1.2 the storage of observers and observables was changed from std::list to std::set. I believe that this would also help in the context above, yet not fully resolve the problem. Anyway, the improved code should be moved to the object handler, too, yes? Is there by the way a special reason for duplicating the code? Is it to keep the object handler independent of QL in some sense?

Thank you
Peter

------------------------------------------------------------------------------
This SF email is sponsosred by:
Try Windows Azure free for 90 days Click Here
http://p.sf.net/sfu/sfd2d-msazure
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev

Book2.xls (41K) Download Attachment