Can I tell Perl that some data is immutable to speed things up?

Perl is really good at writing the types of string / file parsing programs I usually need to do. What I really love is the negligible amount of time it takes me to write fast scripts and dump code compared to C / C ++ / JAVA. However, I want to know how to speed up the process.

For example, I would like to learn how to give Perl hints so that it can make some decisions better, especially things related to strings. It seems to me that Perl copies the string whenever you do something, whether you actually modify the copy later or not. Is this by design (and can I turn this off with some magic?) Or am I reading?

I really want to treat some lines like (const char *

). I'm sure we don't always need everything to be a std :: string with all the baggage involved (let's say a std :: string is similar to a Perl string). Can I give Perl a hint to do this on some lines?

I remember reading in some article (please comment if you can post it) that you can hint to Perl that you will not change any variable and therefore remove excess baggage that would otherwise be needed if you would modify it, etc ..

I believe Perl variables have two internal pointers to one Perl variable - one can store a number and the other a string (character array). Can I always tell Perl to pick one in everything? Can I force Perl to treat some strings as (const char *)

such so they don't mark the functions needed to change them?

For example, I read somewhere (maybe the same article?) That unpack () is faster than substr () because substr () returns an lvalue, so you can work on that too. For example, if I wanted to replace the first two characters of a string with "ef", I could write:

substr(string, 0, 2) = 'ef'; # string now begins with 'ef'

      

Hence, if I don't use this feature of substr (), am I better off using substr?

I just sang through?

+1


a source to share


4 answers


You can set a flag SvREADONLY

on the c variable Readonly::XS

, but this does not improve performance. Efficiency comes from choosing the right algorithm, not from compiler hints. If you want your code to be faster / use less memory, then profile it (see Devel::NYTProf

). When you find a bottleneck, either use a different algorithm there, or switch to use XS

.

Also, if you try to optimize something, make sure the result is really faster, here is the substr vs unpack link:

            Rate unpack substr
unpack 2055647/s     --   -74%
substr 7989875/s   289%     --

      



Here is the reference code.

#!/usr/bin/perl

use strict;
use warnings;

use Benchmark;

my %subs = (
    unpack => sub { return unpack "a3", "foobarbaz" },
    substr => sub { return substr "foobarbaz", 0, 3 }
);

for my $sub (keys %subs) {
    print "$sub => ", $subs{$sub}(), "\n";
}

Benchmark::cmpthese -1, \%subs;

      

+16


a source


generally:

Use good algorithms and don't optimize if necessary. If so, please comment your code and compare your changes. This is a good time to consider XS or Inline :: C as needed.

a (const *) char equvialent:

use constant Foo => 'bar';

creates a minimal subroutine that can be inlined by the perl compiler. You can also create your own built-in persistent functions

avoid extra copying:

A typical Perl idiom does some "extra" copying:

sub foo {
    my $bar = shift;

    ..do stuff with $bar...
}

      

Many people don't understand that Perl passes arguments to subroutines by reference. @_

contains aliases for the arguments of the routine.

Therefore, you can avoid copying your arguments by working directly with @_

:



foo( $big_scalar );

sub foo {
    ..do stuff with $_[0]...
    .. sneakily risk modifying $big_scalar ..
}

      

Of course, this is risky, since if you change the value, you change the value of the call. Use this only when you need to keep a copy of a large file. (Or, you explicitly want to change the calling argument.)

If I need to move a large chunk of data around, but I won't change it, I usually pass it by reference explicitly, rather than messing with @_

;

foo( \$big_scalar );
sub foo {
    my $bar = shift;
    ... do stuff with $$bar ...
    ... can modify $big_scalar, but the pass by ref is explicit ...
}

      

[P] remal optimization is the root of all evil

At least what Donald Knuth said is pretty cool. There is a lot of wisdom in this statement.

Improper optimization (code that should be optimization, but is not) is also very bad.

Code for clarity first. Be sure to include your code to find bottlenecks. Be sure to compare your optimizations to make sure they work. Document your optimized code, maintain some control code - the compiler may not be as responsive tomorrow as it is today.

+7


a source


I am with Hour, testing and profiles of your code. I really doubt that string copying is your bottleneck and you will spend a lot of time on a small win. Even if string copying is indeed the bottleneck, look for the flawed algorithm in your code first. One of the great potential performance gains of Perl over C and Java is that it writes code so quickly, which gives you more time to profile and optimize and improve the algorithm.

If copying strings is really your bottleneck, consider just passing large strings as references. The moral equivalent of a string pointer in C. This will prevent copying. Remember to play them out before using them.

sub foo {
    my $ref = shift;

    print $$ref;
}

$string = "Some string";
foo(\$string);

      

+3


a source


I remember reading in some article (please comment if you can post it) that you can hint to perl that you will not modify any variable, and thus it removes excess baggage that would otherwise required if you have to change it, etc.

I would be right if you were talking about using a constant ... '?

0


a source







All Articles