G'day nzsvz9,

This was something that interested me because I write a lot of Tk programs for personal use, and many of them involve images. I've never run out of memory — possibly because I've got lots to start with; 32GB on my current machine — so it has never occurred to me to check for memory leaks.

Your idea of passing around Tk-related data in a hash is, at least in my opinion, a good one. I do it myself and, in the code below, I've provided some basic examples of my type of usage. I do not, however, use package variables; furthermore, my lexical $TK is hidden from almost all of the code in an anonymous block.

You also need to manage your %TK. You didn't show any working code nor give any idea of how many images you're dealing with or how big they are; however, I suspect this is, at least part of, your memory problem. There may well be all sorts of other data you're carrying around well past its use-by-date.

The following code I ran twice. First without, then with, these two lines of code (they're almost at the end of the script):

(delete $TK->{img}{$name})->delete(); $TK->{gui}{can}->delete('all');

The first run chewed up about 200MB which was immediately reclaimed when I used the "Exit" button. The second run used no appreciable amount of memory; system memory was unchanged after hitting "Exit".

I can't fix your code because you didn't show it. I attempted to keep most of what you outlined in your description. Hopefully, you can get some ideas from what follows to make improvements.

#!/usr/bin/env perl use strict; use warnings; use Tk; { my $TK = {}; $TK->{gui}{mw} = MainWindow::->new(); _build_gui($TK); my ($iter, $id) = (0); $id = $TK->{gui}{mw}->repeat(500, sub { $TK->{gui}{start}->invoke(); $TK->{gui}{mw}->after(200, sub { (shift @{$TK->{gui}{quits}})->invoke(); }); $id->cancel if $iter++ > 1_000; }); } MainLoop; sub _build_gui { my ($TK) = @_; $TK->{gui}{mw}->configure(-title => 'Test Tk::Photo Memory Leak'); $TK->{gui}{mw}->geometry('384x216+100+150'); _build_controls($TK); return; } sub _build_controls { my ($TK) = @_; $TK->{gui}{frame} = $TK->{gui}{mw}->Frame()->pack(); $TK->{gui}{start} = $TK->{gui}{frame}->Button( -text => 'Start', -command => sub { _popup($TK) } )->pack(); $TK->{gui}{frame}->Button( -text => 'Exit', -command => sub { exit } )->pack(); return; } sub _popup { my ($TK) = @_; $TK->{img}{id} = 0 unless exists $TK->{img}{id}; my ($w, $h) = (400, 300); $TK->{gui}{top} = $TK->{gui}{frame}->Toplevel(); $TK->{gui}{top}->geometry("${w}x$h+500+550"); $TK->{gui}{top}->overrideredirect(1); push @{$TK->{gui}{quits}}, $TK->{gui}{top}->Button(-text => 'Quit' )->pack(-side => 'bottom'); $TK->{gui}{can} = $TK->{gui}{top}->Canvas( )->pack(-anchor => 'center', -fill => 'both', -expand => 1); my $name = 'earth' . $TK->{img}{id}++; $TK->{img}{$name} = $TK->{gui}{top}->Photo( $name, -file => Tk->findINC('demos/images/earth.gif') ); $TK->{gui}{can}->createImage( $w/2, $h/2, -image => $name, -anchor => 'center' ); $TK->{gui}{quits}[-1]->configure(-command => sub { (delete $TK->{img}{$name})->delete(); $TK->{gui}{can}->delete('all'); $TK->{gui}{top}->destroy(); }); return; }

You should be able to run that without needing to change anything (except maybe the shebang line). The code itself will run on v5.8 (probably even older versions). The image, earth.gif, comes with Tk (it's used in the Widget Demo) so you should already have that.

— Ken


In reply to Re: Losing my memory by kcott
in thread Losing my memory by nzsvz9

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.