Forum Webscript.Ru

Программирование => Perl => Тема начата: frenky от 04 Марта 2006, 19:10:11

Название: как оптимизировать
Отправлено: 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)

Может можно эту часть кода оптимизировать чтоб она быстрее работала?
Название: как оптимизировать
Отправлено: y8 от 06 Марта 2006, 12:31:58
1) Никогда не используйте foreach для хешей, темболе больших.

[perl]
($key, $value) = each %hash;
[/perl]

2) Если у вас размер массива в процессе жизни менятся не будет, использование for будет более быстрым вариантом, чем foreach.

Можно получить цельный кусок кода? Дабы посмотреть что там на самом деле.

Кстати, заюзайте Time::HiRes для проверки времени выполнения.
Название: как оптимизировать
Отправлено: arto от 06 Марта 2006, 14:20:28
# 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)
#
Название: как оптимизировать
Отправлено: y8 от 06 Марта 2006, 16:48:31
Хм. Версия перла какая? А если while попробовать?
Название: как оптимизировать
Отправлено: arto от 06 Марта 2006, 17:00:21
# perl -V:version
version=\'5.8.7\';
#

while -- это как?
Название: как оптимизировать
Отправлено: y8 от 06 Марта 2006, 17:21:02
Всё, ступил жутко. for и foreach - это синонимы.
А с  while это

my $cnt = scalar(@a);

while ($cnt) {
[do something]
$cnt--;
}

Сейчас смотрю на сколько с while будет быстрее/медленне.
А по поводу foreach keys и while (my ($key, $val) = each %hash) - это действительно быстрее, ибо each не перебирет ключи отделяя их от значений, а тупо отадёт пары в том подрядке в каком, они лежат в памяти. На эту тему есть даже рецепт в cookbook.
Название: как оптимизировать
Отправлено: arto от 06 Марта 2006, 17:35:05
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)
#
Название: как оптимизировать
Отправлено: y8 от 06 Марта 2006, 18:48:59
Элементов в массиве: 10000
for ... OK!
Потраченно: 0.02864с (28.642092с, 1000 итеарций)
foreach ... OK!
Потраченно: 0.02914с (29.141574с, 1000 итеарций)
while ... OK!
Потраченно: 0.02914с (29.141574с, 1000 итеарций)

Разницы в целом нет, но for чуточку быстрее.
Название: как оптимизировать
Отправлено: y8 от 06 Марта 2006, 18:49:57
Код теста, 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));