in reply to memory not freed after perl exits. Solaris.

People,

Firstly THANK-YOU for all your comments.

I half expected a "not another guy blaming memory not freeing" type response.

There were a number of replies and it would be impracticle to reply to each so at the risk of breaking the threading, I have gathered all my responses here.

Generally I've repeated a summary of a suggestion followed by my response.

Now if I can sort out the formatting....



Post the code:

There is about 1000 lines and (almost by definition) I'm not sure which sections to post.

Posting the lot might be asking a lot of your collective patience.


Rerun on a local disk.

I can get the code onto a local disk and run it.

I only have 5 G locally (on /tmp) and I have about 0.5T of log files. I'll try to get a fragment of the log files on to /tmp and rerun.


I'm not forking.


Only 2 zombies after, not sure before I'll rerun and see how many after another run, but this is after several runs.


The script ends normally, not with ^C. It prints a message right near the end and closes the output file correctly (I think!). I often run it in background ^Z, (followed by "bg") but not always. No evidence of it with ps -aux


Free memory isn't decreasing just fragmenting.

I don't know. I'm using vmstat as I described. Is there a better way to assess free memory. It seems to agree with the header in "top"


Am I using "shared name memory"

Not as far as I know, I'm letting perl handle everything in that regard. I just keep adding elements to my hash, sometimes I store it and retrieve a new one. In between I undef the hash name. Don't know if that is necessary or helps. Also I open a lot of files and read from them, I only write to 1 or 2 files. I'm pretty sure I'm closing all the files that I open (which I wasn't a while ago).


Am I storing data on /tmp.

I'm not storing data on /tmp but I do send the STDOUT of the programme to a log file on /tmp.

I don't know if the nature of the /tmp filesystem,

$ df -k .

Filesystem kbytes used avail capacity Mounted on

swap 7077352 1652448 5424904 24% /tmp

Does that mean that it is of type "swap"? Sorry for my ignorance.


run perl -E"$x='x' x 2**31 to flush memory from cache

If I put it in a file and run, I can run **29, if I try **30 I get:

panic: string extend at ./999-workHard.pl line 2.

**29 takes about 4 seconds.

If I run it from the command line:

/usr/bin/perl -e"$x='x' x 2**29"

syntax error at -e line 1, near "="

Execution of -e aborted due to compilation errors.

I don't know how to fix either the limit of **29 or the compilation error when running from command line.


I have no background jobs running.


ps -au username

1 defunct process. No indication of process size.

The name of the programme I'm running isn't in the list.


no ramdisks on this machine


So I wrote the OP yesterday and when I log on today the "free" in top and vmstat has increased, (from ~500m to 2.6G) so maybe it is just the file cache being released over time.

Can someone help me with the "$x='x' x 2**31" thing? This seems like the most promising answer or is it a red-herring?





On a completely separate note, how to I do the formatting sensibly.



Thanks again to everybody.




</BODY> </HTML>
  • Comment on Re: memory not freed after perl exits. Solaris.

Replies are listed 'Best First'.
Re^2: memory not freed after perl exits. Solaris.
by roboticus (Chancellor) on Nov 24, 2010 at 13:01 UTC

    <p>[Workplane]:</p>

    <p>With respect to your comment on formatting help. Hopefully, this can serve as an example. But don't forget the handy links at the bottom of the composing window showing the HTML tags, etc.</p>

    <p>As to your posting a large amount of code. The standard advice I give here is to make a copy of your program, and hack out a large chunk that you really don't believe could be affecting the problem. Then run it. If it truly didn't affect the problem (i.e., you're still losing memory), then make another copy, remove another chunk of code, etc. Eventually, you'll find that the last chunk you deleted caused the problem, and you can examine it in more detail. It also gives you a smaller program to post and ask questions about.</p>

    <p>Yes, it can be a bit time consuming, but I expect you're already at the point where living with the problem is also painful. Give it a try and see what you can do with it.</p>

    <p>...[roboticus]</p>

Re^2: memory not freed after perl exits. Solaris.
by BrowserUk (Patriarch) on Nov 24, 2010 at 12:09 UTC
    Can someone help me with the "$x='x' x 2**31" thing?

    Try:

    perl -e '$x="x" x 2**31'

    All I've done is switch "s for 's and vice versa. That should now run on your Solaris system.

    But you said that you'd got it to run by putting it into a script rather than running it as a one-liner. Did it have the desired affect?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Thanks for the change to quotes. That has made it get further.

      But the result is then the same as before (when I saved it in a file and ran it from there)

      I can run up to **29, but not **30 or **31

      **29 takes about 4 seconds.

      $ perl -e '$x="x" x 2**31' panic: string extend at -e line 1. $ perl -e '$x="x" x 2**30' panic: string extend at -e line 1. $ perl -e '$x="x" x **29' $

      So why can't I run **30 or **31?

        Probably because your OS is setup such that each process can only address a maximum of 2GB. This is the normal configuration for 32-bit OSs.

        And when you do: $x = 'x' x 2**30; It first requests enough memory (1GB) to build the string in. It then requests another 1GB (for $X) to copy the string into. (Dumb, but that's the way it works!)

        As the perl executable is already consuming a few MB from startup, aftr you've allocated the first 1GB, there is not enough virtual memory left in the process to make the copy, so it fails.

        I was using a 64-bit OS which means each process can access much more memory.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        Out of curiosity, what output do you get from running the following on the command line?

        isainfo -v
Re^2: memory not freed after perl exits. Solaris.
by MidLifeXis (Monsignor) on Nov 24, 2010 at 15:04 UTC
    Am I storing data on /tmp.
    I'm not storing data on /tmp but I do send the STDOUT of the programme to a log file on /tmp.
    I don't know if the nature of the /tmp filesystem,
    $ df -k . Filesystem kbytes used avail capacity Mounted on swap 7077352 1652448 5424904 24% /tmp
    Does that mean that it is of type "swap"? Sorry for my ignorance.

    and

    no ramdisks on this machine

    Actually, you do have a ramdisk on the machine. swapfs / tmpfs / ramdisk are functionally the same thing. They will take blocks from your vm system to use for a disk interface to the system.

    Is the size of the logfile in your /tmp filesystem the same as the amount of memory that you are seeing your system go down by?

    --MidLifeXis

      so what I understand from what you wrote:
      by sending the log file (STDOUT) to /tmp I am forcing the system to use memory to hold the log file?
      Is that correct?
      The log file is often larger than the amount of memory which is no longer free (often larger than the system physcial memory)
      Log file may be up to 8G
      Physical Memory = 4G
      Memory "lost" on one run ~ 300M to 2G
      But why does the memory stay lost (not free)?
      What can I do to get it back?
      Shouldn't it be given back when the programme exits and the log file is written to disk (flushed?).

      I log in via a Citrix connection over a (relatively) slow link, so I can't have gigabytes spewing out to an xterm. Sending it to a file on /tmp seemed a good way to keep the output for debugging purposes.

      Would I be better off sending the STDOUT to a file on the NFS?
      That seems like an odd thing if so!

        so what I understand from what you wrote: by sending the log file (STDOUT) to /tmp I am forcing the system to use memory to hold the log file? Is that correct?

        Yes

        The log file is often larger than the amount of memory which is no longer free (often larger than the system physcial memory) Log file may be up to 8G Physical Memory = 4G

        This should make your machine swap like mad. I don't know Solaris that well, on Linux, top and /proc/swaps tell me how much swap is used. I would bet that swap usage is about as large as your log file on /tmp.

        Memory "lost" on one run ~ 300M to 2G

        That would match a machine that has stuffed most of the file written to swap, keeping only the most recently used blocks (i.e. the last few mega/giga bytes) in RAM.

        But why does the memory stay lost (not free)?

        Because you don't delete the logfile?

        What can I do to get it back?

        Delete the logfile from /tmp.

        Shouldn't it be given back when the programme exits and the log file is written to disk (flushed?).

        There is no disk behind /tmp. (Well, there is one, if you count the swap partition, but not in the way there is a disk behind /usr or /var.) The swap filesystem is essentially a ramdisk that can overflow into the swap disk, so you can allocate nearly all of your physical RAM plus nearly all of your swap space for temporary data.

        I log in via a Citrix connection over a (relatively) slow link, so I can't have gigabytes spewing out to an xterm. Sending it to a file on /tmp seemed a good way to keep the output for debugging purposes.

        Write to a real disk local to the machine you are working on. Ask your admins for a reasonable space. /var/tmp should be a world-writeable directory configured to survive a reboot (i.e. on a disk- or flash-based filesystem) and to be machine-specific (i.e. local disk / flash).

        Would I be better off sending the STDOUT to a file on the NFS? That seems like an odd thing if so!

        NFS would put some load on the network, and it is way slower than a local disk or a ramdisk.

        Think about a less verbose log. Try to filter the log on the fly. Something like:

        perl yourscript.pl -foo bar | grep 'Important' > log.txt

        or

        perl yourscript.pl -foo bar | grep -v 'Notice' > log.txt

        or

        perl yourscript.pl -foo bar | grep -v 'irrelevant' | grep -v 'useless' | grep -v 'crap' > log.txt

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re^2: memory not freed after perl exits. Solaris.
by Workplane (Novice) on Dec 12, 2010 at 22:48 UTC

    People,

    OP again. I know not threaded, but so many replies to whom should I reply?

    Thanks. Collectively you seem to have fixed it for me.

    I can't be sure exactly which was the fix but I think the problem was sending the (large) log files to /tmp which it appears on my system to consume memory/swap.

    I've also tried to reduce the log file size.

    I can't be sure exactly what fixed it because a round trip involved rebooting the box which I can't do (I'm remote from it) so I tried all your suggestions in one go and got a successful result. Not very scientific I know.

    Thanks again.

    Geoff.