http://www.perlmonks.org?node_id=1042004

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

use constant LABEL_ARRAY => qw(Title Section Subsection Class Category + Degree Attempt CountOfCounts);
my @label_array = qw(Title Section Subsection Class Category Degree At +tempt CountOfCounts);
I've been thinking about replacing the array definition with the 'constant' definition but a little reading (on google) about using constants seems to indicate that is very little speed improvement. Opinions?

Replies are listed 'Best First'.
Re: 'constant' vs array
by BrowserUk (Patriarch) on Jul 02, 2013 at 14:15 UTC
    but a little reading (on google) about using constants seems to indicate that is very little speed improvement.

    It very much depends upon what you are doing with them.

    For example:

    use constant BOOL => 0; our $BOOL = 0; cmpthese -1,{ const => q[ for(1..1e6){ if(BOOL){ my $n = 1; $n *=$_ for 1 .. 1000; } } ], var => q[ for(1..1e6){ if($BOOL){ my $n = 1; $n *=$_ for 1 .. 1000; } } ] };; Rate var const var 15.1/s -- -22% const 19.4/s 29% --

    Note: The code inside the if block isn't executed in either case; but in the variable version, the value of $BOOL has to be tested every time around the loop in case it changes.

    But with the constant, Perl can see that the value cannot change, so it optimises away the entire if statement; so that 29% performance gain comes simply from not having to test a value that will never change 1e6 times.

    If you want to know what difference your use will make don't ask for opinions; benchmark it.

    Some you'll gain, some you won't; but you'll never loose.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: 'constant' vs array
by Athanasius (Archbishop) on Jul 02, 2013 at 14:07 UTC

    The use constant pragma implements constants as inlinable subroutines, but “In the current version of Perl, list constants are not inlined...” (constant, v5.18.0). Benchmarking on my version (Strawberry Perl v5.16.0) actually shows a significant reduction in speed:

    #! perl use strict; use warnings; use Benchmark qw( cmpthese ); use constant LABEL_ARRAY => qw(Title Section Subsection Class Category + Degree Attempt CountOfCounts); my @label_array = qw(Title Section Subsection Class Category + Degree Attempt CountOfCounts); cmpthese( -1, { array => \&array, constant => \&constant } ); sub constant { my $sum = 0; $sum += length for LABEL_ARRAY; return $sum; } sub array { my $sum = 0; $sum += length for @label_array; return $sum; }

    Output:

    23:59 >perl 660_SoPW.pl Rate constant array constant 155802/s -- -70% array 511619/s 228% -- 0:01 >

    :-(

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: 'constant' vs array (Ignore bad benchmarks: [mod://constant] arrays are (a little) faster!)
by BrowserUk (Patriarch) on Jul 02, 2013 at 15:16 UTC

    A couple of people have benchmarked constant arrays in this thread, but they've both made the same mistake: not checking what their code is doing and thus drawing bad conclusions.

    The problem is that this use constant ARRAY => qw(Title Section Subsection Class Category Degree Attempt CountOfCounts);; does not create an array.

    It creates a subroutine which returns an array as a list; which accounts for the inefficiency.

    On the other hand: This use constant ARRAY => [ qw(Title Section Subsection Class Category Degree Attempt CountOfCounts) ];; creates a subroutine that return a reference to the array, which you can then index efficiently (especially if you use enum for the indexes):

    use constant ARRAY => [ qw(Title Section Subsection Class Category Deg +ree Attempt CountOfCounts) ];; use enum = qw(Title Section Subsection Class Category Degree Attempt C +ountOfCounts);; @array = qw(Title Section Subsection Class Category Degree Attempt Cou +ntOfCounts);; cmpthese -1, { var => q[ for(1..1e6){ my $l = $array[ $category ]; } ], const => q[ for(1..1e6){ my $l = ARRAY->[ $category ]; } ], constenum => q[ for(1..1e6){ my $l = ARRAY->[ Category ]; } ], };; Rate var const constenum var 4.57/s -- -1% -18% const 4.64/s 1% -- -17% constenum 5.57/s 22% 20% --

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      The problem is such a reference is constant, but its members are not:
      ARRAY->[0] = 'not so constant'; print ARRAY->[0];
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        but its members are not:

        I guess if you think you might 'accidentally' modify something you've defined as a constant that might be a problem.

        But the primary uses of constant are:

        1. Giving literals meaningful (symbolic) names.
        2. Making it obvious to yourself and other programmers that this thing is a program defined literal by the use of a CLEARLY_DIFFERENT_SYNTAX.

          Even $UPPER_CASE doesn't achieve that (as well).

          Using variable name syntax for things that are not variable makes no sense.

        3. Availing yourself of the optimisations that come from informing the compiler that this entity is not going to change.

          The oxymoronic read-only variables can not do this.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: 'constant' vs array
by NetWallah (Canon) on Jul 02, 2013 at 14:09 UTC
    Readonly has significantly better syntax, and about the same speed as 'constant' for arrays.

    Adding Readonly::XS makes scalars faster.

                 My goal ... to kill off the slow brain cells that are holding me back from synergizing my knowledge of vertically integrated mobile platforms in local cloud-based content management system datafication.

Re: 'constant' vs array
by kcott (Archbishop) on Jul 02, 2013 at 14:25 UTC

    G'day fionbarr,

    "I've been thinking about replacing the array definition with the 'constant' definition but a little reading (on google) about using constants seems to indicate that is very little speed improvement. Opinions?"

    You'd probably get a better answer if you linked to the articles you've been reading and specified what array operations you were comparing. You've really provided nothing on which to base an opinion.

    Here's a fact though (from constant - CAVEATS):

    "In the current version of Perl, list constants are not inlined ..." [At the time of writing, that link is for v5.18.0]

    Here's timings for accessing the first element (using v5.18.0):

    $ perl -Mstrict -Mwarnings -E ' use Time::HiRes; use constant LABEL_ARRAY => qw(Title Section Subsection Class Cate +gory Degree Attempt CountOfCounts); my @label_array = qw(Title Section Subsection Class Category Degre +e Attempt CountOfCounts); my $x; my $t1 = Time::HiRes::time; $x = (LABEL_ARRAY)[0] for 1 .. 1_000_000; my $t2 = Time::HiRes::time; say $t2 - $t1; my $t3 = Time::HiRes::time; $x = (@label_array)[0] for 1 .. 1_000_000; my $t4 = Time::HiRes::time; say $t4 - $t3; ' 2.28321886062622 0.133409023284912

    So, in that context, there is quite the opposite of any sort of speed improvement. Of course, while you have to access the constant array element like that (i.e. (CONSTANT)[$index]), you're more likely to access a lexical array element like this: $array[$index]

    $ perl -Mstrict -Mwarnings -E ' use Time::HiRes; use constant LABEL_ARRAY => qw(Title Section Subsection Class Cate +gory Degree Attempt CountOfCounts); my @label_array = qw(Title Section Subsection Class Category Degre +e Attempt CountOfCounts); my $x; my $t1 = Time::HiRes::time; $x = (LABEL_ARRAY)[0] for 1 .. 1_000_000; my $t2 = Time::HiRes::time; say $t2 - $t1; my $t3 = Time::HiRes::time; $x = $label_array[0] for 1 .. 1_000_000; my $t4 = Time::HiRes::time; say $t4 - $t3; ' 2.29306197166443 0.0892441272735596

    So, perhaps I do have an opinion on these articles that indicate "very little speed improvement"; and that opinion would be that they are wrong. :-)

    -- Ken

      thanks for the thoughtful replies
Re: 'constant' vs array
by 5mi11er (Deacon) on Jul 02, 2013 at 13:17 UTC
    In either case, the computer must read from memory in order to make use of the data, so no, I would expect nearly no gain moving from one to the other.

    The reason you would choose to use the constant version would be to ensure the array is not changed during program execution.

    -Scott