Что является различием, от 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
Объявление my
в Perl имеет два основных эффекта; один во время компиляции (в котором он выделяет слот в блокноте, содержащем подпрограмму и гарантирует, что все ссылки на это имя в надлежащей области разрешены в этот конкретный слот блокнота), и во время выполнения (в котором он сбрасывает значение этот слот для заполнения на undef
или на какое-то конкретное значение, если вы написали my $ var = foo
).
Часть времени компиляции, конечно, имеет нулевую амортизированную стоимость времени выполнения, но часть времени выполнения запускается один раз каждый раз, когда выполнение проходит через объявление my. Как отмечали другие, ваши два примера имеют разную производительность, потому что они имеют разную семантику в целом - один очищает переменную каждый раз в цикле, а другой нет.
Поскольку приведенные вами примеры программ на самом деле ничего не делают, трудно назвать конкретную причину, по которой один тип объявления был бы лучше другого. Как указывали многие другие плакаты, объявление переменной в цикле каждый раз создает новую переменную.В ваших примерах создание избыточно, но рассмотрите следующие примеры с использованием замыканий.
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, ...)
Таким образом, в этом случае разница во времени на самом деле не имеет значения, поскольку два блока кода работают по-разному. вещи.
Первый цикл пытается сделать объявление переменной для каждой итерации цикла и может привести к ненужному времени обработки.
Конечно, это не так много, но все это может накапливаться со временем, и технически это медленнее, поскольку на каждую итерацию выполняется больше инструкций.
Во-первых, проблема заключается в том, что вы объявляете новую переменную на каждой итерации.
Во-вторых, существует более серьезная проблема определения объема работ.
Попробуйте добавить эту строку после для
в каждом из них, и посмотрите, что произойдет:
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
Объявление my
вне цикла приводит к тому, что объявление выполняется один раз. Во время объявления Perl резервирует память для этой переменной.
Объявление my
внутри цикла приводит к тому, что объявление выполняется в каждом интервале цикла.
my
- это ответ Perl на локальное объявление переменной - local
использовался для чего-то еще и не означает того же, что и в C. Когда вы объявляете переменную внутри loop, он объявляется в локальной области для блока цикла, где блок начинается / заканчивается в каждом интервале. Переменная не только объявляется, но также может быть очищена (разыменована и / или установлена на undef
) в конце блока (хотя это отличается от версий Perl).
Переменные, объявленные вне блока цикла, считаются «глобальными» (не буквально, но в смысле блока цикла). Эти переменные повторно используют свои ячейки памяти, вместо того, чтобы искать новые адреса.