Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

G'day Montain_Gman,

Welcome to the Monastery.

I ran your code unaltered and, like ++choroba noted, was not able to reproduce your problem (i.e. no hangs, crashes, or other problems like that).

I'm running Perl 5.32.0 and Tk 804.035. I have a reasonably high-end rig with a fairly powerful GPU (RTX 2080 Ti). This could easily affect the outcome. What do you have?

The $size variable starts at 410. I increased this, via the Entry box, to 600, then 1000, then 2000. With each increase, rendering was progressively slower (at 2000, the rendering seemed to take some minutes). However, at no point did I experience any hangs or exception messages.

In a current Tk project, I have a canvas with around 2000x1000 pixels. It contains a very large number of elements, which include lines, arcs, rectangles, polygons, as well as Photo and Bitmap images. This renders in about one second: substantially different from what I'm seeing with your code.

"... idletasks ... but I'm not sure exactly what is going on."

There are two methods for updating the display: idletasks() and update(). Both are described in Tk::Widget. You've got the correct one (idletasks()) here but you're only interested in updating the canvas. Change




Calling this intermittently in a for loop is correct; however, you also need to do so after the loop:

for ... (...) { ... if (...) { $canvas->idletasks(); } } $canvas->idletasks();

Unless the if is TRUE on the last iteration, you'll end up with a strip that isn't updated. This fixes that.

You can also play around with the if condition to get an optimal value based on the range of numbers you're expecting.

"... more than say 400x400 pixels worth of stuff on a canvas, it tends to bog down ..."

There are a lot of places where you're repeating operations needlessly. Consider:

for my $i (0..$size-1){ for my $j (0..$size-1){ my $a = ($i%20) > 9; my $b = ($j%20) > 9; my $c; if($a^$b){ $c = sprintf("#%02X0000",$i%0xFF); } else { $c = sprintf("#00%02X00",$j%0xFF); } $USE[$i][$j]=$c; } }

The calculations involving $i are repeated on every iteration of the inner loop; however, the results only change in the outer loop. $a and $b are special variables, so you should avoid using them; but, you don't need either of them, nor do you need $c. You could have written:

for my $i (0..$size-1){ my $i_col = $i%0xFF; my $i_mod20_9 = $i%20>9; for my $j (0..$size-1){ $USE[$i][$j] = $i_mod20_9^($j%20>9) ? sprintf("#%02X0000",$i_col) : sprintf("#00%02X00",$j%0xFF); } }

Having done that, you may notice that both of those sprintf calls can only result in 256 different values each. With your small, default $size of 410, the inner loop is entered 168,100 times; that number grows exponentially as $size is increased. If you precalculated all 512 possible sprintf values, you could reduce the code further to something like:

for my $i (0..$size-1){ my $i_col = $i%0xFF; my $i_mod20_9 = $i%20>9; for my $j (0..$size-1){ $USE[$i][$j] = $i_mod20_9^($j%20>9) ? $reds[$i_col] : $greens +[$j%0xFF]; } }

You could go a step further by caching @USE. If $size doesn't change, nor will @USE: don't run through those hundreds of thousands (or potentially millions) of iterations when you already have the result. You could use something along these lines:

if (exists $use_cols{$size}) { @USE = @{$use_cols{$size}}; } else { for ... { ... $USE[$i][$j] = ...; } $use_cols{$size} = [@USE]; }

If you look down the code to the next nested for loops, you'll see something similar: you're calculating $i*$ps and $i*$ps+$ps on every iteration of the inner loop when the value only changes in the outer loop. Also, the assignment to $c is pointless: you could write "-fill=>$USE[$i][$j],-outline=>$USE[$i][$j]" and have no need of the extra $c variable.

I'll leave it there as I think I've written more than enough. Look through all of your code for further opportunities for improvement.

— Ken

In reply to Re: Perl Tk canvases / abuse... by kcott
in thread Perl Tk canvases / abuse... by Montain_Gman

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

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2021-08-02 09:56 GMT
Find Nodes?
    Voting Booth?
    My primary motivation for participating at PerlMonks is: (Choices in context)

    Results (23 votes). Check out past polls.