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

hello, I was wondering why tr///; was used instead of s///; in the following:?
$text = 'Welcome+to+perlmonks.org'; $text =~tr/+/ /;
I just changed the format a bit but basically I was wondering why not just use $text =~s/\+/ /g; ?

Replies are listed 'Best First'.
Re: transliterate
by japhy (Canon) on Jul 27, 2001 at 21:44 UTC
    Because tr/// is technically faster for char-to-char conversions than s///g.

    _____________________________________________________
    Jeff japhy Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      japhy, that's what I would've thought too, but I timed it using Benchmark and the times were actually comparable. One runthrough tr would be a second or two faster, the next one s/// was faster by a second or two. However, as the iteration count went up, the substitution was actually faster consistently.
      use Benchmark; timethese(250000, { one => sub { $string = "blah+blah+blah"; $string =~ tr/+/ /; }, two => sub { $string = "blah+blah+blah"; $string =~ s/\+/ /g; } }); print "\n"; timethese(2000000, { one => sub { $string = "blah+blah+blah"; $string =~ tr/+/ /; }, two => sub { $string = "blah+blah+blah"; $string =~ s/\+/ /g; } });
      NOTE: I did use counts between 250,000 and 2,000,000 as well.

      Maybe its my system, but I thought that this was strange.

      Amel - f.k.a. - kel

        Which version of perl are you using?

        5.005_03 seems to have a really slow tr///, that actually is slower than s/// (singe celeron 466)
        Benchmark: timing 250000 iterations of one, two... one: 1 wallclock secs ( 0.83 usr + 0.00 sys = 0.83 CPU) two: 1 wallclock secs ( 0.74 usr + 0.00 sys = 0.74 CPU) Benchmark: timing 2000000 iterations of one, two... one: 7 wallclock secs ( 6.71 usr + 0.00 sys = 6.71 CPU) two: 6 wallclock secs ( 5.93 usr + 0.00 sys = 5.93 CPU)

        However, 5.6.1 (on a dual p3 800) tr seems to be almost twice as fast.
        Benchmark: timing 250000 iterations of one, two... one: 1 wallclock secs ( 0.26 usr + 0.00 sys = 0.26 CPU) @ 96 +1538.46/s (n=250000) (warning: too few iterations for a reliable count) two: 1 wallclock secs ( 0.46 usr + 0.00 sys = 0.46 CPU) @ 54 +3478.26/s (n=250000) Benchmark: timing 2000000 iterations of one, two... one: 2 wallclock secs ( 2.06 usr + 0.00 sys = 2.06 CPU) @ 97 +0873.79/s (n=2000000) two: 4 wallclock secs ( 3.68 usr + 0.00 sys = 3.68 CPU) @ 54 +3478.26/s (n=2000000)

        I don't know too much about the tr/// and s/// code, but it looks like someone went and optimized tr/// between 5.005 and 5.6.1. (Would someone who knows (japhy?) please comment on this?)
        I'm pressed for time, but I'd like you to do two things:
        1. Try varied lengths of strings, with varied numbers of plus signs.
        2. Use a negative count (that is, -5), which tells Perl to run them for that many (positive) seconds.
        Please report your findings. I'll be back whenever I can. (I'm talking at TPC today, and I should really be at the talks right now!)

        _____________________________________________________
        Jeff japhy Pinyan: Perl, regex, and perl hacker.
        s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: transliterate
by Agermain (Scribe) on Jul 27, 2001 at 21:46 UTC
    Simple. Tr's faster, because it doesn't have to do all the funky "regex" style matching. Tr just loops through the characters one-by-one, and if it finds a + it changes it to a space. If it doesn't, it doesn't spend any more time figuring out what not to do, whereas s/// will. In other words, s/// is like using a power drill when a screwdriver would do.

    Update: Okay, maybe it's not technically faster, but in theory it's supposed to be faster. I'm guessing that the s/// regex command gets more bit-level optimization than anything else in perl, just because it's such a swiss army knife of functionality; maybe tr got left behind on optimization?

    "In fact, we must do just the opposite and remain ever-vigilant, striving to ensure that we stop the Urkels of tomorrow before they gain power. Only by demanding full accountability can we reverse the shameful legacy of man's inanity to man."

      thanks much :)