http://www.perlmonks.org?node_id=1058288


in reply to Re^2: Perl tk gui hangs when large data thrown to it
in thread Perl tk gui hangs when large data thrown to it

the code is too huge to include here.

Simplify it. That is, make a simplified version of it for testing. Just the single widget that displays your changing data, the timer routine that processes inbound packets and the updateDisplay() routine. This would be invaluable to you for testing the maximum throughput you can expect of Tk and your tcp code.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
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.

Replies are listed 'Best First'.
Re^4: Perl tk gui hangs when large data thrown to it
by ghosh123 (Monk) on Oct 15, 2013 at 11:41 UTC

    Well, even the simplified version will be quite long. I have described the entire thing here, but may be it is not sufficient for you to guess.
    FYI, I am giving the update gui routine here, which is getting called from the server function as and when it has read some data from the socket.

    sub updateGui { my $self = shift; my $data = shift; my $hlist = $self->{jobTree}; my @cellInfo = split( /\s/, $data ); my $font = "{helvetica} -12 bold"; my $style1 = $self->{displaybaseObj}->getItemStyle( $hlist, 'text', -foreground => 'black', -anchor => 'nw', -background => "$cellInfo[2]", -font => $font ); my $num1 = int( rand(2) ) + 1; my $num2 = int( rand(2) ) + 0; my $subnode1 = $cellInfo[0] . "." . $num1; my $subnode2 = $cellInfo[0] . "." . $num1 . "." . "0" . "." . $num +2; $hlist->itemConfigure( $subnode1, 2, -text => "$cellInfo[1]", -style => $style1 ); $hlist->itemConfigure( $subnode2, 2, -text => "$cellInfo[1]", -style => $style1 ); }

    The $data to this routine is like "500 running green" i.e a gui row , some status of that and a colour separated by single space. $hlist is the Tree widget which just a bit extension of the built in HList.pm Tk module.

    Let me see , if I can post a very simplified version of it.

Re^4: Perl tk gui hangs when large data thrown to it
by ghosh123 (Monk) on Oct 15, 2013 at 12:04 UTC

    I am just including a very very simplified code which is just one perl file only. Please change the repeat frequency to test it. The gui would show better performance if the repeat frequency is increased to 1sec , currently it is 1ms only.
    My requirement is :

    1. what is the reason for the gui to get hung when we are trying to change some 100 rows on it every 1 ms . Can not perl tk handle this ? is this a limitation ?

    2. is their any other mechanism to make it work, provided i will repeat it every 1 ms and would try to change 100 rows of it randomly.

    use Tk; use Tk::HList; use Time::HiRes qw/usleep/; my $mw = MainWindow->new(); my $hlistframe = $mw->Frame()->pack( -fill => 'both', -expand => 1 ); my $font = "{helvetica} -12 bold"; my $hl = $hlistframe->Scrolled( 'HList', -scrollbars => 'ose', -columns => 7, -header => 1, #-height => 10, -width => 50, -command => sub { print "test\n"; }, )->pack( -fill => 'both', -expand => 1 ); my $num = $hl->Label( -text => "Number", -anchor => 'w', -font => $fon +t ); $hl->headerCreate( 0, -itemtype => 'window', -widget => $num ); my $name = $hl->Label( -text => "ID", -anchor => 'w', -font => $font ) +; $hl->headerCreate( 1, -itemtype => 'window', -widget => $name ); my $DOB = $hl->Label( -text => "Job", -anchor => 'w', -font => $font ) +; $hl->headerCreate( 2, -itemtype => 'window', -widget => $DOB ); my $Address = $hl->Label( -text => "status", -anchor => 'w', -font => +$font ); $hl->headerCreate( 3, -itemtype => 'window', -widget => $Address ); my $style1 = $hl->ItemStyle( 'text', -selectforeground => 'black', -anchor => 'nw', -background => 'green', -font => $font ); my $style2 = $hl->ItemStyle( 'text', -selectforeground => 'black', -anchor => 'nw', -background => 'red', -font => $font ); my $style3 = $hl->ItemStyle( 'text', -selectforeground => 'black', -anchor => 'nw', -background => 'blue', -font => $font ); sub populate { my $path = 0; foreach my $entry ( 1 .. 100 ) { insertData( $path, $entry ); $path++; } } &populate(); sub insertData { my ( $path, $entry ) = @_; $hl->add($path); # print "path $path \n"; $hl->itemCreate( $path, 0, -text => "$path" ); # , -style => $ +style1); $hl->itemCreate( $path, 1, -text => "someid" ); # , -style => $ +style1); $hl->itemCreate( $path, 2, -text => "test" ); #, -style => $s +tyle1); $hl->itemCreate( $path, 3, -text => "running", -style => $style1 ) +; } $mw->repeat( 1, \&changeItem ); my $flag; sub changeItem { my %flag; foreach ( 1 .. 100 ) { my $randRow = int( rand(20) ); print "randRow $randRow \n"; if ( $flag{$randRow} ) { $hl->itemConfigure( $randRow, 3, -text => "pending", -style => $style2 ); $hl->itemConfigure( $randRow, 3, -text => "waiting", -style => $style2 ); $flag{$randRow} = 0; print "if flag ", $flag{$randRow}, "\n"; } else { print "else flag 0\n"; $hl->itemConfigure( $randRow, 3, -text => "finished", -style => $style3 ); $hl->itemConfigure( $randRow, 3, -text => "aborted", -style => $style3 ); $flag{$randRow} = 1; print "else flag ", $flag{$randRow}, " \n"; } #usleep(100); #sleep 2 ; } } MainLoop;

      I think you're just expecting too much. You cannot see an event that only lasts 1 millisecond so there's no point updating you display that quickly. If you data really is changing that quickly just cache it until the next screen update.

      I've changed the repeat to 20ms, removed the prints from changeitem and increased then rand row to 100, and your code works. But even 50 updates per second are too many, I'd try 10 or less, as you don't really need video rates.

        Ok, I understand.
        But I even tried the same thing with thread, where the inter-process communication is happening in one thread and the gui is in another thread. I hoped threading would be able to handle the scenario but it could not. As I have explained earlier in this post, the client is sending data with usleep(some number) interval of time, the server reads the data and writes that into a shared variable. The gui thread reads from that shared variable and invokes the relevant gui updateDisplay() routine to update the gui.
        But this also not bringing things up if the usleep is very small amount of time and I am trying to change some 1k rows every millisecond. But how can not threading the handle this problem ? Why this gui is not responding ?

      The bottom line is that your gui is not "hanging"; it is just never getting around to updating because you are keeping it so busy that it never has time to update the screen.

      You have a fundamental disconnect in your understanding of how Tk -- and guis in general -- work; between what you are expecting to happen and what actually happens.

      This is perhaps best illustrated by this piece of your code:

      $hl->itemConfigure( $randRow, 3, -text => "pending", -style => $style2 ); $hl->itemConfigure( $randRow, 3, -text => "waiting", -style => $style2 );

      First you change the text to "pending"; then immediately to "waiting". You are expecting the screen to update between the two changes such that a user might notice the change. That will never happen. Firstly, by default, the screen will not update until the program has nothing else to do. That means, at least until your changeItem() subroutine returns. So the first of the two changes in each branch of your while loop are completely redundant because they will never be shown on screen.

      But it is much worse than that. Your subroutine changes 100 items (twice each) every time it is called. And you are (attempting to) calling it every millisecond. So -- if that were possible, which it isn't -- each of the two changes would be on-screen for a maximum of half a millisecond. The human eye/brain simply cannot detect changes at anything close to that rate.

      Historically, movies were shown at 24 frames/second. Recently there have been moves to project movies at 48 frames/sec -- though most experts conclude that this is at least 50% higher than any human being can distinguish any difference. You are trying to achieve a rate of 2000 frames/sec.

      Besides that it is totally impossible; what would be the point? Jet fighter pilots reaction times can -- under absolutely ideal conditions of total immersion and rigourously-trained, muscle-memory actions -- achieve physical (finger) reactions to visual stimuli in just under 1/10th of 1 second.

      What are you hoping your user/operator will be able to do with seeing statuses change 2000 times a second?


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.