CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Memory leak In my code (https://www.cfd-online.com/Forums/openfoam-programming-development/225223-memory-leak-my-code.html)

frobaux March 19, 2020 02:28

Memory leak In my code
 
Hey everyone, I written a pretty heavy code, which runs. The problem is that it accumulate memory usage with time and I have no clue to where it can be. Is there a debug option or something that I can use to check if something is getting constructed and not destructed.



I'm using a lot of(almost exculsively) autoPtr = new ... to store datas, maybe it is the origin. They are meant to be dynamically modified (ownership transferred with = or redefined completely with an other = new... )



Basically I have a mesh of 61777 cells, with all tests passing (except 4 faces that are severy non-orthogonal). And at the beggining, I use something like 0.72Gb of RAM. But after 40 000time step I'm at like 8Gb.



Thank you a lot for your help
Fabien

ybapat March 20, 2020 06:53

You can use tools like valgrind to detect memory leaks.

frobaux March 20, 2020 08:29

Thank you for your answer. That's what I've done (with debugging mode compilation)
The problem is that I do not understand the results to be honnest.

I tried both with the memcheck tool and massif tool.



In my code it seems that stuffs are allocated, and never removed. I have a lot of trouble finding the culprit(s). I would use massif for that kind of problem, but I have a nice graph but cannot identify when in my code this happens.

Gerry Kan March 23, 2020 03:48

Dear Fabien:

Just a very naive question ... did you also call the delete function for each of the dynamically allocated memory for your variables once you don't need them anymore?

Gerry.

ybapat March 23, 2020 23:37

I have used the tool some time back. I think you should find some document online to explain output. Also if you are using autoPtr then the are meant for memory handling and call delete in destructor.

frobaux March 24, 2020 06:39

Yes, this it the main reason why I use autoPtr.

Well, I think I found "the" (probably "a") problem:
I need to frequently use interpolation on a tmp<volScalarField>. I do It with

Code:

autoPtr<interpolation<Type>> interp
                (
                    interpolation<Type>::New("cellPoint", potField)
                );

Where potField is a volScalarField. Which in turns call
Code:

template<class Type>
Foam::interpolationCellPoint<Type>::interpolationCellPoint
(
    const GeometricField<Type, fvPatchField, volMesh>& psi
)
:
    interpolation<Type>(psi),
    psip_
    (
        volPointInterpolation::New(psi.mesh()).interpolate
        (
            psi,
            "volPointInterpolate(" + psi.name() + ')',
            true     
        )
    )
   
{}

During this process, the registery (with debug activated) tells me that:
Code:

 

Constructing IOobject called volPointInterpolation of type IOobject
objectRegistry::checkIn(regIOobject&) : GlobMesh : checking in volPointInterpolation of type regIOobject

And then that
Code:

Constructing IOobject called volPointInterpolate(potField) of type IOobject
objectRegistry::checkIn(regIOobject&) : GlobMesh : checking in volPointInterpolate(potField) of type regIOobject

The problem is that both of them are NEVER checkOut (I've written small scripts that compares for each variable how many time they were checkIn and checkOut)
I think this is were the memory fills! Each time this intep is called, It seems that I add and never delete the member psip_ (a pointField) of interpolationCellPoint.H

I tried to add

Code:

interp.clear();
But nothing changes...

Any advice on this??

Gerry Kan March 24, 2020 09:37

Fabien:

You are right with the autoPtr. I am still stuck in old school, preferring to taking care of memory allocation by myself!

Code:

autoPtr<interpolation<Type>> interp
                (
                    interpolation<Type>::New("cellPoint", potField)
                );

and

Code:

        volPointInterpolation::New(psi.mesh()).interpolate
        (
            psi,
            "volPointInterpolate(" + psi.name() + ')',
            true     
        )

Without going through the code in detail, I am not sure if the destructor in interp auto pointer also calls the corresponding destructor of the new interpolation object that is used to initialize your object, and by extension the new volPointInterpolation. My hunch is it doesn't. So even if you handle the memory management yourself in the interpolation (instead of the autoPtr that you are currently having), the New'd objects will still be in memory.

Would it be possible to create the tmp<volScalarField> in question before hand, and use it as argument and then delete() them by yourself.

Gerry.

frobaux March 24, 2020 10:23

Well, I didn't found a clean solution. that really erases the members of interp.
I had confirmation when I tried to print what is contained in the objectRegistry, that a lot of volScalarFields accumulate inside in (everyone named volPointInterpolate(blabla)) where blabla reprensents the operation done to compute "potField".


The (not clean workaround) is to use the same name, because "cache" is used (see bove). That way, the volPointInterpolate is cleared when renewed...


If someone wants, here is the small script to execute on your log to get everything written in the object registries.

Code:

CheckInAndOut.sh:
#!/bin/bash

### Compare variables that had been checked in and out from openFoam
### usage: ./CheckInAndOut.sh log.interFoam
### Care that you need to have regIOObject 1; as a debugSwitch enabled.
function esc_var()
{
    #escape the characters in  a given variable to be able to grep with this variable
    a=$(printf %q $@)
    echo ${a//\+/\\+}
}


# list every val that are checkedIn. the name of the var is the seventh. last awk is to register variables only once
listVal=$(cat $1 | grep  "checkIn(reg" | awk  '{printf  $7"\n"}' | awk '!a[$0]++')


for var in $listVal; do

    i=$(esc_var $var)

    # how many time this variable is registered
    nIn=$(cat $1 | grep -E "checking in $i " | wc -l)

    # how many time this variable is checked out
    nOut=$(cat $1 | grep -E  "checking out $i$" | wc -l)

    # compare, if it does not match, print what was found:
    if [ "$nIn" != "$nOut" ]; then
        echo
        echo
        echo "variable name: $var"
        echo $i
        echo "nIn $nIn nOut $nOut diff:"$(calc $nIn-$nOut)
        cat $1 | grep --line-number -E -e "checking in $i " -e " checking out $i$"
    fi
done


frobaux March 26, 2020 05:32

Quote:

Originally Posted by Gerry Kan (Post 762697)
Fabien:

You are right with the autoPtr. I am still stuck in old school, preferring to taking care of memory allocation by myself!

Code:

autoPtr<interpolation<Type>> interp
                (
                    interpolation<Type>::New("cellPoint", potField)
                );

and

Code:

        volPointInterpolation::New(psi.mesh()).interpolate
        (
            psi,
            "volPointInterpolate(" + psi.name() + ')',
            true     
        )

Without going through the code in detail, I am not sure if the destructor in interp auto pointer also calls the corresponding destructor of the new interpolation object that is used to initialize your object, and by extension the new volPointInterpolation. My hunch is it doesn't. So even if you handle the memory management yourself in the interpolation (instead of the autoPtr that you are currently having), the New'd objects will still be in memory.

Would it be possible to create the tmp<volScalarField> in question before hand, and use it as argument and then delete() them by yourself.

Gerry.


Well, this is what I tought, to be honest, I have tought about this method.
Creating a "localCellPoint" method that does not store it into "cache". Or takes as an entry the volPointInterpolate field.

But the problem of this is that in that case I could not replace "cellPoint" by another preexisting method of interpolation. As I said in my previous post (I didn't see your answer at that time), I ve managed to find a way to avoid the problem, even if I know it is not really clean nor elegant.


All times are GMT -4. The time now is 00:33.