Perl: Почему это медленнее для объявления (моих) переменных в цикле?

Что является различием, от POV интерпретатора, между следующим следующие программы:

#!/usr/bin/perl -w

use strict;

for (1..10000000) {
    my $jimmy = $_**2;
}

и

#!/usr/bin/perl -w

use strict;

my $jimmy;
for (1..10000000) {
    $jimmy = $_**2;
}

"время" сообщает для первой программы:

real    0m1.519s
user    0m1.513s
sys     0m0.004s

и для второго:

real    0m1.023s
user    0m1.012s
sys     0m0.002s
6
задан flies 23 July 2010 в 19:12
поделиться

5 ответов

Объявление my в Perl имеет два основных эффекта; один во время компиляции (в котором он выделяет слот в блокноте, содержащем подпрограмму и гарантирует, что все ссылки на это имя в надлежащей области разрешены в этот конкретный слот блокнота), и во время выполнения (в котором он сбрасывает значение этот слот для заполнения на undef или на какое-то конкретное значение, если вы написали my $ var = foo ).

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

10
ответ дан 8 December 2019 в 14:39
поделиться

Поскольку приведенные вами примеры программ на самом деле ничего не делают, трудно назвать конкретную причину, по которой один тип объявления был бы лучше другого. Как указывали многие другие плакаты, объявление переменной в цикле каждый раз создает новую переменную.В ваших примерах создание избыточно, но рассмотрите следующие примеры с использованием замыканий.

my @closures;
my $jimmy;

for (1 .. 10) {
    $jimmy = $_** 2;
    push @closures, sub {print "$jimmy\n"};
}

и этот:

my @closures;

for (1 .. 10) {
    my $jimmy = $_** 2;
    push @closures, sub {print "$jimmy\n"};
}

В каждом случае код создает серию ссылок на код, но в первом примере, поскольку все ссылки кода относятся к одному и тому же $ jimmy , каждая из них напечатает 100 когда звонили. Во втором примере каждая ссылка на код будет печатать разные числа (1, 4, 9, 16, 25, ...)

Таким образом, в этом случае разница во времени на самом деле не имеет значения, поскольку два блока кода работают по-разному. вещи.

3
ответ дан 8 December 2019 в 14:39
поделиться

Первый цикл пытается сделать объявление переменной для каждой итерации цикла и может привести к ненужному времени обработки.

Конечно, это не так много, но все это может накапливаться со временем, и технически это медленнее, поскольку на каждую итерацию выполняется больше инструкций.

2
ответ дан 8 December 2019 в 14:39
поделиться

Во-первых, проблема заключается в том, что вы объявляете новую переменную на каждой итерации.

Во-вторых, существует более серьезная проблема определения объема работ.

Попробуйте добавить эту строку после для в каждом из них, и посмотрите, что произойдет:

print $jimmy;

И попробуйте еще:

my $jimmy;
for (1..10000000) {
    my $jimmy = $_**2;
}
print $jimmy;

Подробнее:

A my declares перечисленные переменные для быть локальным (лексически) по отношению к окружающему блок, файл или eval. Если более одного значение указано, список должен быть в скобках.

http://perldoc.perl.org/functions/my.html

Вам, вероятно, также будет полезно прочитать это:

http://perldoc.perl.org/perlsub. html # Private-Variables-via-my% 28% 29

1
ответ дан 8 December 2019 в 14:39
поделиться
  1. Объявление my вне цикла приводит к тому, что объявление выполняется один раз. Во время объявления Perl резервирует память для этой переменной.

  2. Объявление my внутри цикла приводит к тому, что объявление выполняется в каждом интервале цикла.

my - это ответ Perl на локальное объявление переменной - local использовался для чего-то еще и не означает того же, что и в C. Когда вы объявляете переменную внутри loop, он объявляется в локальной области для блока цикла, где блок начинается / заканчивается в каждом интервале. Переменная не только объявляется, но также может быть очищена (разыменована и / или установлена ​​на undef ) в конце блока (хотя это отличается от версий Perl).

Переменные, объявленные вне блока цикла, считаются «глобальными» (не буквально, но в смысле блока цикла). Эти переменные повторно используют свои ячейки памяти, вместо того, чтобы искать новые адреса.

0
ответ дан 8 December 2019 в 14:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: