How to disable print() function buffering in perl?

K

KJ

Hello,

I'm having a touch of trouble with a fairly simple program that I am
writing. It is a program that executes some interesting sorting
routines (I prefer using my own sort since it allows greater control
and debugging output, especially when the data set I'm using is very
large and "dirty" - ie. many erroneous values that I filter out during
the sort.)

Anyway, on to my question... The program has a statement such as
this:

$sortcount=0;
$debug=1;
while($condition)
{
if($debug)
{
$sortcount++;
if($sortcount%100000==0)
{
print(".");
}
}
<<SORTING CODE GOES HERE>>
}

My problem is this - with the program setup as above, the text gets
buffered for some reason (and doesn't appear on the screen at
run-time). I want the program to output a period (.) to the terminal
for every 100000 executions of the sort subroutine. When I execute
the code above, it outputs all of the periods after the sort
subroutine is finished. HOWEVER, when I run this code:

$sortcount=0;
$debug=1;
while($condition)
{
if($debug)
{
$sortcount++;
if($sortcount%100000==0)
{
print("$sortcount\n");
}
}
<<SORTING CODE GOES HERE>>
}

The program outputs the $sortcount number as the program is executing
and the sort is being performed.

My logic for why this is happening is this: PERL optimizes the code
(as all good compilers do) and erroneously thinks that since the "."
output is static, it is "unimportant" and can be buffered. In the
latter case, though, it sees that $sortcount is a dynamic variable
that is modified within the sort function's loop and deems it as
"important" - therefore outputting it to the screen without buffering
as the loop is executing.

Any ideas on how I can force PERL to deem that little period (.) as
important enough to output at runtime (and thus, disable print
buffering)? Any help or ideas that anyone can provide would be
greatly appreciated.

<<On a side note, I know there is a command "cerr <<" in C++ that
outputs a line of text as an "error" to the screen. Basically it is a
high-priority call to the print queue and followed by an immediate
buffer flush. Is there such an error output in PERL that I could use?
Keep in mind, this is for debugging purposes and will NOT be used in
the program on a regular basis... >>

Thanks,
KJ
 
L

Lukas Mai

KJ said:

[print "." vs print "$sortcount\n"]
My logic for why this is happening is this: PERL optimizes the code
(as all good compilers do) and erroneously thinks that since the "."
output is static, it is "unimportant" and can be buffered. In the
latter case, though, it sees that $sortcount is a dynamic variable
that is modified within the sort function's loop and deems it as
"important" - therefore outputting it to the screen without buffering
as the loop is executing.

No, it's because STDOUT is line buffered by default, so "\n" forces
a flush.
Any ideas on how I can force PERL to deem that little period (.) as
important enough to output at runtime (and thus, disable print
buffering)? Any help or ideas that anyone can provide would be
greatly appreciated.

$| = 1;

$| is documented in perldoc perlvar. See also
http://perl.plover.com/FAQs/Buffering.html
<<On a side note, I know there is a command "cerr <<" in C++ that
outputs a line of text as an "error" to the screen. Basically it is a
high-priority call to the print queue and followed by an immediate
buffer flush. Is there such an error output in PERL that I could use?
Keep in mind, this is for debugging purposes and will NOT be used in
the program on a regular basis... >>

It's Perl, not PERL. There is STDERR, and it's unbuffered by default.

HTH, Lukas
 
J

Jürgen Exner

KJ wrote:
[...]
My logic for why this is happening is this: PERL optimizes the code
(as all good compilers do) and erroneously thinks that since the "."
output is static, it is "unimportant" and can be buffered. In the
latter case, though, it sees that $sortcount is a dynamic variable
that is modified within the sort function's loop and deems it as
"important" - therefore outputting it to the screen without buffering
as the loop is executing.

Actually no. Or not quite. Any decend OS/IO-library buffers output. And the
newline simply triggers a flush of the output buffer.
No compile-time optimization involved at all.
Any ideas on how I can force PERL to deem that little period (.) as
important enough to output at runtime (and thus, disable print
buffering)? Any help or ideas that anyone can provide would be
greatly appreciated.

Well, the first place to search for help would be the Perl documentation,
wouldn't it.
The FAQ actually has a nice entry: "perldoc -q buffer" or "perldoc -q
flush":
"How do I flush/unbuffer an output filehandle? Why must I do this?"
<<On a side note, I know there is a command "cerr <<" in C++ that
outputs a line of text as an "error" to the screen. Basically it is a
high-priority call to the print queue and followed by an immediate
buffer flush. Is there such an error output in PERL that I could use?
Keep in mind, this is for debugging purposes and will NOT be used in
the program on a regular basis... >>

Well, just write to stderr instead of to stdout

jue
 
M

Mike Mayer

Jürgen Exner said:
Well, just write to stderr instead of to stdout

Be careful here. Standard out and standard error are more than just
two different buffering schemes... They are two different output
streams. Often (maybe even most of the time) both of these streams
appear in your terminal window. But, if you are attempting capture
the output via a pipe (either on the command line or via a
pipe/fork/exec from within code) you will not capture both the
standard out and standard error streams unless you explicitly
merge them into a single stream (again either via the command
line---in a shell dependent fashion---or via a dup in code).

I have seen more than one tool cause consternation because it
sent output to standard error or error messages to standard out.

mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top