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

I'm using CGI.pm to write a CGI script and out of necessity, I have to do a lot of printing and I'm unsure of the best way to write it from a efficiency or style standpoint.

I ran a benchmark (output to the console, not to a browser) using this code:

use Benchmark qw/cmpthese/; use CGI; our $cgi = new CGI; cmpthese 5000,{ per_line => <<'EOFCODE', # Loop 10,000 times at 1 output per loop for a total of # 10,000 outputs. for (my $i = 0, $i == 10000, $i++){ print $cgi->p('This is a test.'); } EOFCODE # The following l concat => <<'EOFCODE', # Loop 1,000 times at 10 outputs per loop for a total of # 10,000 outputs. for (my $i = 0, $i == 1000, $i++){ print $cgi->p('This is a test.').$cgi->p('This is a test.'). $cgi->p('This is a test.').$cgi->p('This is a test.'). $cgi->p('This is a test.').$cgi->p('This is a test.'). $cgi->p('This is a test.').$cgi->p('This is a test.'). $cgi->p('This is a test.').$cgi->p('This is a test.'); } EOFCODE comma => <<'EOFCODE', # Loop 1,000 times at 10 outputs per loop for a total of # 10,000 outputs. for (my $i = 0, $i == 1000, $i++){ print $cgi->p('This is a test.'), $cgi->p('This is a test.'), $cgi->p('This is a test.'), $cgi->p('This is a test.'), $cgi->p('This is a test.'), $cgi->p('This is a test.'), $cgi->p('This is a test.'), $cgi->p('This is a test.'), $cgi->p('This is a test.'), $cgi->p('This is a test.'); } EOFCODE };

And got these results:

Rate concat comma per_line concat 747/s -- -0% -88% comma 749/s 0% -- -88% per_line 6098/s 716% 715% --

It would seem, from this, that printing one line at a time is clearly most efficient, even though it had to loop through 10x more times. However, I don't know if that is conclusive, or if code efficency alone should dictate the style the program is written in.

I have come for guidance: should I make each of my print statements its own line, should I join them with commas, or should I concatenate them as strings? I'm also willing to accept that it doesn't really matter at all. Thanks in advance.

Replies are listed 'Best First'.
Re: Proper way to print a large number of strings
by FamousLongAgo (Friar) on Jan 07, 2003 at 15:09 UTC
    Premature optimization is the root of all evil - D. Knuth

    Optimize for readability. print is very fast, however you call it, unless you are doing something crazy. And you're not. Ultimately the best way to do it is the way that lets you come back to the program many weeks later and be able to find what you need quickly.

    If your program bottlenecks on print I will eat my foot.

Re: Proper way to print a large number of strings
by Aristotle (Chancellor) on Jan 07, 2003 at 15:47 UTC
    Most of the time, embedding HTML in your code, be it in strings or CGI function calls, is a mistake, unless what you're going to write is a really short script. perrin's templating system comparison is an excellent place to start on your module choice. Personally, I prefer the shooting star, Template Toolkit II, but you might also just use (f.ex) Text::Template if you don't want to learn a dedicated templating language.

    Makeshifts last the longest.

Re: Proper way to print a large number of strings
by hardburn (Abbot) on Jan 07, 2003 at 14:55 UTC

    I'm also willing to accept that it doesn't really matter at all.

    That's probably the correct answer. Since this is a CGI program, you're almost certainly going to be limited by I/O long before printing time on the CPU becomes an issue. You should format your code in the most readable way, which is usually a heredoc.

      I did consider that, but that doesn't seem to properly handle the OO references (unless I'm missing something obvious). For example, when I run this:

      use CGI; $cgi = new CGI; print << "HEREDOC"; $cgi->p("Test.") HEREDOC <code> I get <code>CGI=HASH(0x119960)->p("Test.")
      when I really want <p>Test.</p>.
        use CGI; $cgi = new CGI; print << "HEREDOC"; $cgi->p("Test.") HEREDOC
        I get CGI=HASH(0x119960)->p("Test.")

        What you want to do is take a reference to your object, and interpolate it via a scalar reference. Look at the following:

        $cgi->p('test') | V \$cgi->p('test') | V ${\$cgi->p('test')}

        In Perl 6, ${...} becomes a mere scalar, and no longer a scalar reference, so you'll be able to write ${$cgi->p('test')} which will be pretty cool. Until then, you'll have to make do with using the above hack. Sometimes this is acceptable, sometimes it's better to do something like:

        print 'stuff ' . $q->b( $q->i( 'and' )) . ' nonsense'

        It all depends on what comes out as being more readable.


        print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
        print $cgi->p( $_ ), "\n" foreach split( /\n\n/, <<"EOT" ); Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi rhoncus, est in pulvinar volutpat, massa erat gravida ipsum, sit amet pharetra lorem nulla eu odio. Integer nec velit. Integer commodo. Duis dui. Aliquam erat volutpat. Pellentesque quis turpis vitae ante egestas imperdiet. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam scelerisque. Vivamus mi dolor, bibendum vitae, eleifend at, lobortis sit amet, leo. EOT