http://qs1969.pair.com?node_id=784055

RAS230 has asked for the wisdom of the Perl Monks concerning the following question:

I don't have much experience with perl/tk, but I'm using it for a script made to run on windows which gathers some data then creates and opens an html file with the output. The problem is that it's just too slow.

I wrote up a quick example to show the problem. All the interface does is provide a button to start doing the work but even that seems to take 30-45 seconds each time it's run.

Half a minute plus might not even sound that bad, but the results are near instant if I run the same thing after commenting out all the perl/tk stuff. I'm willing to take a hit in performance in exchange for the simple interface, but this seems excessive. I'm wondering if the problem is just that I'm not using more perl/tk specific ways of doing the same things which might run much faster.

Like I said, I'm not very familiar with perl/tk, in fact this is only the second time I've used it for something, so please forgive me my ignorance and while your in a forgiving spirit, please forgive my example code (it's ugly but does show the problem).

#!perl -w use strict; require Tk; use Tk; my $row=1; my $filename="example_out.htm"; my %stuff1=( 'thing01_a' => "value01_a", 'thing02_a' => "value02_a", 'thing03_a' => "value03_a", 'thing04_a' => "value04_a", 'thing05_a' => "value05_a", 'thing06_a' => "value06_a", 'thing07_a' => "value07_a", 'thing08_a' => "value08_a", 'thing09_a' => "value09_a", 'thing10_a' => "value10_a" ); my %stuff2=( 'thing01_b' => "value01_b", 'thing02_b' => "value02_b", 'thing03_b' => "value03_b", 'thing04_b' => "value04_b", 'thing05_b' => "value05_b", 'thing06_b' => "value06_b", 'thing07_b' => "value07_b", 'thing08_b' => "value08_b", 'thing09_b' => "value09_b", 'thing10_b' => "value10_b" ); sub do_this() { open FILE, "> $filename" or die "ERROR WRITTING FILE: $filename\nSyste +m reported $!"; print FILE << "HTMLSTUFF"; <HTML> <HEAD><TITLE>TABLE O' STUFF</TITLE> <STYLE> table {border-style: solid;border-width: 2;border-color: #005A80;} td {padding:4px;border:0;text-align: center; white-space: nowrap} .header {background-color: #005A80;text-decoration: none;text-align: c +enter;color: white; font-weight: bold;} .line2 {background-color: lightblue;} .line1 {background-color: white;} </STYLE> </HEAD> <BODY> <P> <TABLE> <TR CLASS=header><TD>THING 1</TD> <TD>THING 2</TD> <TD>THING 3</TD> <T +D>THING 4</TD> <TD>THING 5</TD> <TD>THING 6</TD> <TD>THING 7</TD> <TD +>THING 8</TD> <TD>THING 9</TD> <TD>THING 10</TD></TR> HTMLSTUFF if ($row == 1) {print FILE "\n<TR CLASS=line1>"; $row=2;} elsif ($row +== 2) {print FILE "\n<TR CLASS=line2>"; $row=1;} foreach (sort keys(%stuff1) ) { print FILE "<TD CLASS=time>$stuff1{$_} +</TD>";} print FILE "</TR>"; if ($row == 1) {print FILE "\n<TR CLASS=line1>"; $row=2;} elsif ($row +== 2) {print FILE "\n<TR CLASS=line2>"; $row=1;} foreach (sort keys(%stuff2) ) { print FILE "<TD CLASS=time>$stuff2{$_} +</TD>";} print FILE "</TR>"; print FILE "\n</TABLE></BODY><HTML>"; close FILE; system "start /b $filename"; } my $fsize=12; my $main = MainWindow->new(); $main->title("Button Window"); $main->configure(-background=>'#c0c0c0'); $main->optionAdd('*BorderWidth' => 1); my $bottom = $main->Frame(-background=>'#c0c0c0')->pack(-expand=>0, -f +ill=>'both'); my $sub_button=$bottom->Button(-width=>40, -background=>"#c0c0c0", -fg +=>'black', -text=>'CLICK ME', -font => ['Courier', 10], -command=>\&c +lick); $sub_button->pack(-side => "bottom", -anchor => "s", -expand => "n", - +fill => "none"); MainLoop(); sub click() { do_this(); }

Replies are listed 'Best First'.
Re: Why so slow when using Perl/Tk?
by GrandFather (Saint) on Jul 29, 2009 at 00:09 UTC

    When is the delay? Is it from 'run the script' until 'window with button opens' (which can be attributed to Tk, but is a delay I've never seen and don't reproduce), or is it from 'click the button' until 'Browser window opens' (which is very likely something specific to your default browser and nothing to do with Perl or Tk)?

    BTW, you don't need to require and use the same module - just use use.


    True laziness is hard work
Re: Why so slow when using Perl/Tk?
by BrowserUk (Patriarch) on Jul 28, 2009 at 22:59 UTC

    What OS/Perl/Browser/Proxies are you running? Cos with Vista/AS1004/Opera/None, the HTML is displayed instantaneously when I click the button if the browser is running and takes (empirically) less than a second if it isn't.

    In essence, you should probably look carefully at your particular set-up rather than attributing the problem to Tk.


    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.
      I'd been seeing the problem on a few workstations, all winXP using activestate's perl (5.8.8) with either Firefox 3.5 or IE 8 as the default browser.

      I'd been testing with the browser already open but windows would start it up to load the file if it weren't. For me the slowdown starts as soon the button is clicked. The button itself even stays in a depressed state for almost the entire wait. After seeing that you guys aren't getting the same results I pulled out an old test box (XP with IE 6) and it worked fine on that machine so it looks like the problem might be limited to the workstations.

      I originally ruled out browser issues and focused on perl/tk as the source of the trouble because removing the perl/tk lines always fixes the problem and it's easy to blame the thing you least understand, but I'm going to have dig into this a little closer.

      This could be a problem with the install on the affected machines or even antivirus/security software related...

      Thanks once again for the help and the tips!

      I'll let you all know what the trouble was if I manage to track the source of this down to anything more interesting than a bad image or a conflict with some obscure internal application.

        You are writing each line separately?
        I suggest storing everything you want to write in a variable, and then write it all out in one big I/O operation. The writing process should be faster, and AV/Sec software won't be tempted to rescan the changed file fifty thousand times.

Re: Why so slow when using Perl/Tk?
by ww (Archbishop) on Jul 28, 2009 at 22:28 UTC
    Knowing even less about Tk than you profess to know, this is not an answer to the question asked, but rather a distinctly non-rhetorical question in reply:

    Why are you using Tk merely to create a button?

    It seems likely to me that executing this script is not significantly less demanding (of the ultimate user) than it would be to execute a non-GUI script from the command line.

    Granted, when you write the code to populate your hashes (rather than hardcoding them), your CLI script will likely need argument(s) [source file(s) and output file] but if the Monks who can answer your actual question conclude that the issue is in some- or large-part the extra overhead of Tk, you're faced with a choice: "to take a hit in performance in exchange for the simple interface" or to offer the user(s) a usage prompt or training.

      No, the actual interface isn't just a button. :) If that were the case I'd agree that it wouldn't be worth the trouble. In general I'd rather just run things from the command line which is why this is only my 2nd attempt at using perl/tk. :)

      In the actual script none of the data is hard coded. All the input gets put into the interface (text boxes, drop downs etc) and then that data is processed and used to populate the hashes/html table/etc.

      None of that extra stuff was a major contributor to the speed problem however, so I kept the perl/tk stuff as simple as possible in my example.

      If the speed is all just overhead and there's nothing for it than I'll have to start looking at other options. The problem seems to be output related more than anything. It's strange, but I've noticed that if I write the output to a plain text file and just open it with notepad it does seem a bit faster. I may have to settle with that, but I'd lose a lot in the formatting/spacing department.

        Eminently reasonable. Seems sensible!

        But your distinction between a plain text file and the .html output of your OP puzzles me again, as any difference should be negligible: the .html source is, to all intents and purposes as far as writing the file is concerned, a "plain text file."

        Or does your actual script open a browser after writing the output? That, of course, would add a bit more overhead. In that case, you cantrim the rendering time by assigning width to table and the ten tds.

        In any case, it may be useful to profile your actual script: see http://search.cpan.org/~timb/Devel-NYTProf-2.10/lib/Devel/NYTProf.pm.

        OTOH, it may be even more useful to await better answers from Tk gurus here.

Re: Why so slow when using Perl/Tk?
by Argel (Prior) on Jul 28, 2009 at 23:04 UTC
    I'm not really seeing any major delays on the Solaris SPARC system I am using here (the only thing that has Perl and Tk on it). Quite frankly, you are not doing that much, so why it is taking so long is a mystery to me. I'm not not sure if you are running it with "-w" but if so then is the Tk module generating a lot of warnings? I don't know if it was written with warnings in mind or not and I believe the "-w" will force warnings on everywhere. You might want to try running the script without warnings or just switch to "use warnings" which will affect just your code. Also, you shouldn't need a "require Tk". If it only works with that then you may want to look into why that's the case.

    There is one Tk trick I have heard of that could help as well. The trick is to hide the window, create the rest of the GUI, and then display it. The changes for this are shown below.

    #.... my $main = MainWindow->new(); # Add this line to hide the window $main->withdraw; $main->title("Button Window"); $main->configure(-background=>'#c0c0c0'); $main->optionAdd('*BorderWidth' => 1); my $bottom = $main->Frame(-background=>'#c0c0c0')->pack(-expand=>0, -f +ill=>'both'); my $sub_button=$bottom->Button(-width=>40, -background=>"#c0c0c0", -fg +=>'black', -text=>'CLICK ME', -font => ['Courier', 10], -command=>\&c +lick); $sub_button->pack(-side => "bottom", -anchor => "s", -expand => "n", - +fill => "none"); # Add these two lines to display the window after you have finished cr +eating the GUI $main->deiconify; $main->raise; MainLoop(); #...

    Elda Taluta; Sarks Sark; Ark Arks