Forum Webscript.Ru
Программирование => Perl => Тема начата: frenky от 04 Марта 2006, 19:10:11
-
$v_="0:0:0";
%vorot=(
\'252,2,4\'=>\'14#4,15#2,15#3,15#4,15#5,15#6,16#5,16#6,16#7,16#8,16#9,17#7,17#8,17#9,17#10,18#8,18#9,18#10,19#7,19#8,19#9,20#6,20#7,20#8,21#5,21#6,21#7,22#4,22#5,22#6,23#3,23#4,23#5,24#2,24#3,24#4,25#1,25#2,25#3\'
);
if ($v_) {
my ($r,$g,$b)=split(/:/,$v);
my $es = $tite->colorAllocate($r,$g,$b);
foreach $bs(keys %vorot)
{
@kord=split(/,/,$vorot{$bs});
foreach $ff(@kord) {
my ($x,$y)=split(/#/,$ff);
$tite->setPixel($x,$y,$es);
}
}
}
проц пентиум 2.4 Ghz 512 MB
timethis 1000: 57 wallclock secs (51.91 usr + 0.11 sys = 52.02 CPU) @ 19.22/s (n=1000)
Может можно эту часть кода оптимизировать чтоб она быстрее работала?
-
1) Никогда не используйте foreach для хешей, темболе больших.
[perl]
($key, $value) = each %hash;
[/perl]
2) Если у вас размер массива в процессе жизни менятся не будет, использование for будет более быстрым вариантом, чем foreach.
Можно получить цельный кусок кода? Дабы посмотреть что там на самом деле.
Кстати, заюзайте Time::HiRes для проверки времени выполнения.
-
# perl -MBenchmark=timethese -e \'@a = ( "1" )x102400; timethese ($ARGV[0],{A => "foreach (\\@a) {}",B => "for (\\@a) {}"})\' 10000
Benchmark: timing 10000 iterations of A, B...
A: 198 wallclock secs (86.33 usr + 0.22 sys = 86.55 CPU) @ 115.54/s (n=10000)
B: 198 wallclock secs (87.53 usr + 0.32 sys = 87.85 CPU) @ 113.83/s (n=10000)
#
-
Хм. Версия перла какая? А если while попробовать?
-
# perl -V:version
version=\'5.8.7\';
#
while -- это как?
-
Всё, ступил жутко. for и foreach - это синонимы.
А с while это
my $cnt = scalar(@a);
while ($cnt) {
[do something]
$cnt--;
}
Сейчас смотрю на сколько с while будет быстрее/медленне.
А по поводу foreach keys и while (my ($key, $val) = each %hash) - это действительно быстрее, ибо each не перебирет ключи отделяя их от значений, а тупо отадёт пары в том подрядке в каком, они лежат в памяти. На эту тему есть даже рецепт в cookbook.
-
btw,
# perl -MBenchmark=timethese -e \'$a{"a$_"} = "b$_" foreach (1..$ARGV[0]); timethese ($ARGV[1],{A => "foreach (keys %a) { my \\$v = \\$a{\\$_}; }",B => "while (my (\\$k,\\$v) = each %a) {}"})\' 10240 1000
Benchmark: timing 1000 iterations of A, B...
A: 24 wallclock secs (11.59 usr + 0.02 sys = 11.61 CPU) @ 86.13/s (n=1000)
B: 26 wallclock secs (12.28 usr + 0.03 sys = 12.31 CPU) @ 81.23/s (n=1000)
#
-
Элементов в массиве: 10000
for ... OK!
Потраченно: 0.02864с (28.642092с, 1000 итеарций)
foreach ... OK!
Потраченно: 0.02914с (29.141574с, 1000 итеарций)
while ... OK!
Потраченно: 0.02914с (29.141574с, 1000 итеарций)
Разницы в целом нет, но for чуточку быстрее.
-
Код теста, Benchmark.pm я не очень доверяю, из-за точности вычеслений.
#!/usr/bin/perl -w
use Time::HiRes qw(gettimeofday tv_interval);
use strict;
my @a = (1 ... 10000);
my $count = 1000;
my @c = (1 ... $count);
open (NULL, \'>nul\'); # nul для венды, или /dev/null для никсов
my $foreach = sub
{
foreach (@a)
{
print NULL $_;
};
};
my $for = sub
{
for (@a)
{
print NULL $_;
};
};
my $map = sub
{
my $cnt = @a;
while ($cnt)
{
print NULL $a[$_];
$cnt--;
}
};
my @foreach;
my @while;
my @map;
print "Элементов в массиве: ", scalar @a ,"\\n";
print "Выполняем $count прогонов for ...";
for (@c)
{
my $t0 = [gettimeofday];
&$for;
push (@while, tv_interval($t0));
}
print "OK!\\n";
my $ttl = 0;
map { $ttl += $_ } @while;
my $avrg = $ttl / scalar(@while);
printf("Потраченно: %.5f (%f, %s)\\n", $avrg, $ttl, scalar(@while));
print "Выполняем $count прогонов foreach ...";
for (@c)
{
my $t0 = [gettimeofday];
&$foreach;
push (@foreach, tv_interval($t0));
}
print "OK!\\n";
$ttl = 0;
map { $ttl += $_ } @foreach;
$avrg = $ttl / scalar(@foreach);
printf("Потраченно: %.5f (%f, %s)\\n", $avrg, $ttl, scalar(@foreach));
print "Выполняем $count прогонов while ...";
for (@c)
{
my $t0 = [gettimeofday];
&$map;
push (@map, tv_interval($t0));
}
print "OK!\\n";
$ttl = 0;
map { $ttl += $_ } @foreach;
$avrg = $ttl / scalar(@map);
printf("Потраченно: %.5f (%f, %s)\\n", $avrg, $ttl, scalar(@map));