Заголовок конечно провокационный, но бенчмарк показывает, что вариант с числовой инициализацией переменной на 20% быстрее(тестировал на 5.12).
#/usr/bin/perl -w use v5.10; use strict; use warnings; use Benchmark ':all'; cmpthese( -5, { integer_init => sub { my $i = 0; $i++ for ( 1 .. 10000 ); }, string_init => sub { my $i = '0'; $i++ for ( 1 .. 10000 ); }, } ); # Rate string_init integer_init #string_init 1769/s -- -18% #integer_init 2147/s 21% --
Разгадка данной особенности довольно проста. При инициализации Perl сохраняет число, как строку. И результат инкремента сохраняет в строковом виде!!! Именно так :).
perl -MDevel::Peek -e 'my $i = "1"; print Dump $i; $i++; print Dump $i;'
SV = PV(0x604bc8) at 0x62d318
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x61ec50 "1"\0
CUR = 1
LEN = 8
SV = PV(0x604bc8) at 0x62d318
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x61ec50 "2"\0
CUR = 1
LEN = 8
SV = PV(0x604bc8) at 0x62d318
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x61ec50 "1"\0
CUR = 1
LEN = 8
SV = PV(0x604bc8) at 0x62d318
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x61ec50 "2"\0
CUR = 1
LEN = 8
С декрементом такого не будет. В принципе любая числовая операция (даже числовое сравнение, например $i < 100) заставит Perl хранить число как число, а не как строку.
for (my $i='10'; $i < 20; $i++) {} # это будет работать нормально, поскольку есть числовое сравнение.
5 коммент.:
my $i = '0';
Почему же он не должен сохранять в строковом виде?
Такой же инкримент вполне работоспособный:
perl -e "my$q='AA'; for(1..5){$q++; print ' '.$q;}"
AB AC AD AE AF
Вот здесь более понятно, то Перл работает со строками, а не с числами:
perl -e "for(my$q='AA'; $q ne'BB'; $q++) {print $q.\"\n\";}"
КАК?!! Как Вы до этого примера додумались? :)))
При инициализации строкой - он должен сохранять строку, но после числового инкремента мог бы и как число хранить ( операция числового сравнения приводит же строку к числу). Если мы инициализировали числом, то Perl работает с числами. Работа с числом быстрее.
В текущей реализации я вижу следующие бонусы:
1. Общий алгоритм инкремента для буквенных строк и чисел. Буквенный инкремент - полностью аналогичен, только используется другая основа для системы исчисления(26 вместо 10) и другие знаки ( a..z вместо 0..9)
2. Не нужно работать с флоатами.
3. В большинстве случаем мы все равно используем переменную в числовом сравнении.
4. Возможно экономия памяти(только возможно :) ), поскольку при переходе на числовое хранение, строка в памяти все равно остается.
perl -MDevel::Peek -e '$i = "z"x1000; $i = 9999; print Dump $i'
В любом случае идея поста заключается том, что работать с числами нужно как с числами :)
Пример конечно немного надуманный, но скажу честно, я в жизни не встречал, чтобы кто-то определял переменную числом в кавычках и потом бы ее инкрементировал. Но возможно, кто-то что-то новое для себя из этого поста вынес :)
Отправить комментарий
Не забудьте добавить себя в постоянные читатели и включить уведомления о новых комментариях, либо воспользуйтесь RSS каналом ;)