Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Trying to track down memory leak(s)
Message
De
23/09/2011 10:18:45
 
 
Information générale
Forum:
Visual FoxPro
Catégorie:
Problèmes
Versions des environnements
Visual FoxPro:
VFP 9 SP2
Divers
Thread ID:
01398453
Message ID:
01524466
Vues:
102
>>>>>What did you find out after implementing this trick?
>>>>>BTW, adding call to this procedure from multithreaded VFP dll in each 50 iterations made no effect in our case.
>>>>
>>>>My vague memory is that Bernard's trick didn't really help, though I don't remember for sure.
>>>>
>>>>I added code to the app that lowers its overall memory load by doing some garbage collection and so forth. (We have a bunch of collections that tend to grow and grow and grow.) We got it down to the point that it hasn't been a problem for the customers.
>>>>
>>>>Tamar
>>>
>>>The class I'm working on does not use collections at all. It uses a few arrays and it also passes big strings in and out. Also it calls sqlexec (as a method) in a loop. I'll try to comment sqlexec calls and see if it helps to memory. If yes, then I have a plan of how to re-write this dll to use local cursor. If not, then I think the path should be to re-write this dll in .NET
>>
>>
>>No idea whether this will help
>>
>>Years ago, I had a class method that had a local array with objects in it. The objects held references to other objects, etc - a whole hierarchy
>>
>>The class called that method which allocated a bunch of objects (with the hierarchy beneath them) . The objects were stored in a local array
>>After the method call other methods were called and it was quite cpu-intensitive
>>
>>
>>What I found is that the destroy event of the objects in the array did not fire upon exit of the method, but later when foxpro encountered an idle state to do the garbage collection
>>
>>The only way I found to have the destroy fired was to (1) release the array or (2) store null to array prior to exiting the method
>>
>>I am now entering 'speculation' mode
>>
>>(1) Foxpro does not perform garbage collection until it finds time to do it (idle state or perhaps doevents)
>>(2) It may be the case here especially if strings are stored in a local array
>>
>>
>>Try to release all local variables (certainly the arrays and the big strings) of the method prior to its return
>
>Hi Gregory,
>
>The arrays in this class only hold static values - no object references stored in arrays. I added explicit release to a few main methods of all strings - it didn't help. Right now I'm running with commented calls to mySQLExec method - will see if it help.
>
>Are there any other tips?
>
>Say, one method that is always called is coded like this:
>
>protected procedure Parse
>      &&parse a parameter out of an XML string
>      lparameters tcSource, tcSearch, tcType, tnForceLength
>      local lnPCount, lcSource, lcTag1, lcTag2, lnAt1, lnAt2, lvRetVal, lvX
>
>      &&VerbosityLevel set to 3 because this one can FILL up a log file!
>      this.write_log('Entering method...', program(), '3')
>
>      lnPCount=pcount()
>      if lnPCount<4
>         tnForceLength=-1
>         if lnPCount<3
>            tcType="C"
>         endif
>      endif
>
>      lcSource  = upper(tcSource)
>      lcTag1    = "<" + upper(tcSearch) + ">"
>      lnAt1     = at(lcTag1, lcSource )
>
>      if lnAt1=0
>         this.write_log('Returning: .NULL. Start Tag '+lcTag1+' Not Found', program(), '3')
>         return .null.
>      endif
>
>      lnAt1    = lnAt1+len(lcTag1)
>      lcSource = upper(substr(tcSource, lnAt1))
>      * lcSource = LEFT(lcSource, lnAt1)
>      lcTag2   = "</" + upper(tcSearch) + ">"
>      lnAt2    = iif(tnForceLength>0, tnForceLength, at(lcTag2, lcSource))
>
>      if lnAt2=0
>         this.write_log('Returning: .NULL. End Tag ' + lcTag2 + ' Not Found', program(), '3')
>         return .null.
>      endif
>
>      lvRetVal = substr(tcSource, lnAt1, lnAt2-1)
>
>      if len(lvRetVal) < 10000
>         this.write_log('Returning: '+lvRetVal+' for tag '+lcTag1, program(), '3')
>      else
>         this.write_log('Returning: '+left(lvRetVal,1000)+' (remainder of large string truncated) for tag '+lcTag1, program(), '3')
>      endif
>      do case
>         case tcType == "N"
>            lvRetVal = val(lvRetVal)
>            ** FP# 15356 - Strip decimals if there is no remainder
>            lvRetVal = iif(lvRetVal % 1 = 0, int(lvRetVal), lvRetVal)
>         case tcType == "D"
>            if substr(lvRetVal,1,1)=='{'
>               lvRetVal=evaluate(lvRetVal)
>               if vartype(lvRetVal)='T'
>                  lvRetVal=ttod(lvRetVal)
>               endif
>            else
>               if at(' ',lvRetVal)>0
>                  lvRetVal=substr(lvRetVal, 1, at(' ',lvRetVal)-1)
>               endif
>               lvRetVal=ctod(lvRetVal)         &&time portion removed if present
>            endif
>         case tcType == "T"
>            if substr(lvRetVal,1,1)=='{'
>               lvRetVal=evaluate(lvRetVal)
>            else
>               lvX=ctot(lvRetVal)
>               if empty(lvX) and at('T',lvRetVal)=0   &&requires a T in some string formats such as 2003-01-02T00:00:00
>                  lvRetVal=ctot(strtran(lvRetVal,' ','T',1))
>               else
>                  lvRetVal=lvX
>               endif
>            endif
>         case tcType == "L"
>            lvRetVal=inlist(upper(lvRetVal),'.T.','TRUE','YES','Y')
>      endcase
>      release tcSource, tcSearch, tcType, tnForceLength
>      return m.lvRetVal
>      endproc
>
>
>Do you think this particular method can be a source of the error?
>
>The external application calls this dll with the 'Invoke' call passing an XML string with parameters. Then invoke method parses the string, calls appropriate method of the class and returns back usually an xml string or a string.
>
>UPDATE. With commented MySQLExec the first call of GetItem method takes 0.02 sec. and last call takes 0.14 seconds, so there is still a memory leak.


(1) try releasing lcSource as well
(2) If the method does not change tcSource, pass it by reference - but do not release it here
(3) You have multiple exit points (release )

(4) I do not think that the difference between .14 sec and 0.02 sec is an indicator of a memory leak
Gregory
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform