Как "мой" быстрее, чем "локальный" в Perl?

Цитата из PerlMonks: разница между моим и локальным,

Но в реальной жизни они работают практически одинаково? Да. Вроде. Итак, когда вы должны их использовать?

Используйте мой, когда сможете (это быстрее, чем локальный)...

Я знаю лексическую и динамическую разницу в области видимости между my и local, как обсуждалось в этот поток SO, но я я не уверен, почему my "быстрее".

Что именно мы имеем в виду, когда говорим, что переменная my быстрее, чем переменная local в Perl?

Ответ 1

Использование local для переменной означает, что ее предыдущее состояние нужно куда-то вставить в стек и снова восстановить, когда локальная область будет удалена. Использование переменной my для переменной просто создает совершенно новую переменную, которая затеняет предыдущую переменную с тем же именем - предыдущая полностью не тронута и не нуждается ни в каком сохранении. Он просто лежит в ожидании, когда локальная область выходит из системы, и она снова видна.

Это нажатие/выключение в стек требует ресурсов; там много работы под капотом, чтобы убедиться, что это работает правильно. (Учитывайте такие случаи, как исключение, которое создается в локальной области действия или обработчик сигнала. Я уверен, что вы можете придумать больше.)

Кроме того, что более эффективно, использование my гораздо логичнее. Как программист, вводящий локальную переменную $foo, вам не нужно беспокоиться о семантической причине предыдущей версии $foo, какие данные уже могут быть в ней, или действительно, если был уже создан foo. Если когда-нибудь спустится предыдущая декларация $foo, ваш код local $foo сломается, но my $foo будет совершенно счастлив. Будьте хорошим программистом и держите свой код в хорошо инкапсулированных фрагментах, что означает использование лексического охвата как можно больше. Вполне возможно написать большое приложение и никогда не нуждаться в переменных пакета/глобальной области вообще, особенно когда вы используете хорошо разработанные классы OO.

Ответ 2

local, вероятно, медленнее из-за необходимости сохранить старое значение, но скорость local vs my не должна вообще входить в дискуссию. Экономия скорости незначительна:

           Rate local    my
local 7557305/s    --   -2%
my    7699334/s    2%    --

и особенности этих двух радикально различны. Вышеприведенные результаты взяты из следующего эталона:

#!/usr/bin/perl

use strict;
use warnings;

use Benchmark;

our $x;

my %subs = (
    local => sub {
        local $x = 42;
        return $x;
    },
    my => sub {
        my $x = 42;
        return $x;
    }
);

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

Benchmark::cmpthese -1, \%subs;