I've been playing with Term::ReadKey for a few days and read somewhere that poorly written code using the ReadKey function could bog down a CPU. I decided to write a small program and see what would happen:
#!/usr/local/bin/perl use Term::ReadKey; use Time::HiRes; use strict; my @char; ReadMode 4; # Turn off controls keys while (lc $char[0] ne "q") { while (not ($char[0] = ReadKey(-1))) { # Time::HiRes::sleep 0.1; } print $char[0]; select((select(STDOUT), $| = 1)[0]); #flush STDOUT buffer } ReadMode 0; # Reset tty mode before exiting
I ran the above code under Solaris 7/5.6.1, Solaris 8/Perl 5.6.1 and Solaris 7/Perl 5.005_02. Note that these are disparate CPUs. It's the trends I concerned with. I then eyeballed top and came up with some interesting results:
1) When the statement Time::HiRes::sleep 0.1; was commented out, the programs CPU utilization rose steadily to levels of 25, 50 and 85% (respectively) over a 4 minute period of time and then stayed at that level.

2) When the statement Time::HiRes::sleep 0.1; was not commented out, the program CPU utilization started out low (0.06, 0.09, 1.83%) and decreased to 0% after two minutes.

I guess that something in the OS is capping the poor utilization in case 1, but even so, the keyboard response times do not appear to suffer. OTOH, why does the utilization fall to zero for case 2, again regardless of keyboard activity?

Apparently, a little sleep can prevent a lot of pain. It would be interesting to see if similar results are achieved on different platforms. Would anyone like to share some insight on this behaviour? Also, is there a better way besides sleep to achieve more desirable CPU performance?

If the code and the comments disagree, then both are probably wrong. -- Norm Schryer

Replies are listed 'Best First'.
Re: Sleep, don't Weep
by jwest (Friar) on Aug 23, 2001 at 00:47 UTC
    In case 1, you're essentially asking Perl to, as fast as it can, keep checking to see if a key has been pressed. This means that your program is constantly in a 'Run' state, unless forced to give up the CPU for another program.

    In fact, that's what's helping to cap the process's CPU utilization. The scheduling algorithm (one of them, anyway - Solaris has several) in the kernel is forcing your program to temporarily give up the CPU, and your process is being rescheduled with a lower priority because it's asking to do so much, meaning it'll take it an extra bit of time to make its way back onto the CPU.

    If you voluntarily give up the CPU, by blocking on a resource or by sleep()ing, you get scheduled with a higher priority than those who don't. Which is another factor leading toward why your keyboard response times don't drop - processes that spent a lot of time blocked on IO functions manage to get higher priority.


    Hope this serves to illuminate...

    --jwest

    -><- -><- -><- -><- -><-
    All things are Perfect
        To every last Flaw
        And bound in accord
             With Eris's Law
     - HBT; The Book of Advice, 1:7
    
Re: Sleep, don't Weep
by Mungbeans (Pilgrim) on Aug 22, 2001 at 16:05 UTC
    My understanding of the CPU utilization is that it's an average. In case 2 your script is spending most of it's time asleep, and waking briefly to check for a key press, so the CPU average is very small.

    The initial CPU hit is due to the perl program startup and memory allocation for the process I suspect.

    My 2p.

    "The future will be better tomorrow." ... from the collected wisdom of George W Bush.