I guess I should provide some real code.
below is a tiny module I grabbed from my project which is not that privacy
but sufficient for discussion.
#/usr/bin/perl
use warnings;
use 5.010;
use Carp;
use DB_File;
{
my %sum_cache;
my %deviation_cache;
tie %sum_cache => 'DB_File', "sum_cache_tmp", O_RDWR|O_CREAT, 0666 or
croak "can not create cache file!";
tie %deviation_cache => 'DB_File', "deviation_cache_tmp",
O_RDWR|O_CREAT, 0666 or croak "can not create cache file!";
sub get_sum
{
my ($i, $n, $opens_ref) = @_;
my $key = join ',', $i, $n;
unless(exists $sum_cache{$key})
{
my $inner_key = join ',', $i - 1, $n;
my $sum = 0;
if(exists $sum_cache{$inner_key})
{
$sum = $sum_cache{$inner_key} - ${$opens_ref}[$i - $n] +
${$opens_ref}[$i];
}else
{
$sum += $_ foreach @{$opens_ref}[$i - $n + 1 .. $i];
}
$sum_cache{$key} = $sum;
}
return $sum_cache{$key};
}
sub get_deviation
{
my ($i, $n, $mean, $opens_ref) = @_;
my $key = join ',', $i, $n;
unless(exists $deviation_cache{$key})
{
my $sum = 0;
$sum += ($_ - $mean) ** 2 foreach @{$opens_ref}[$i - $n + 1 .. $i];
$deviation_cache{$key} = sqrt($sum / ($n - 1));
}
return $deviation_cache{$key};
}
sub cal_using_simple_scheme
{
my($n1, $n2, $n3, $klines_ref) = @_;
my @opens = map {$_->{open}} @$klines_ref;
croak "Wrong argnument. Should all be positive values" if ($n1 <= 0 || $n2
<= 0 || $n3 <= 0);
return [(0) x @opens] if $n2 <= 1;
my $n = $n1 > $n2 ? $n1 : $n2;
my @res;
my @upper_bound;
my @lower_bound;
for my $i (0 .. $#opens)
{
if($i < $n - 1)
{
push @upper_bound, undef;
push @lower_bound, undef;
next;
}
my $sum1 = get_sum($i, $n1, \@opens);
my $mid = $sum1 / $n1;
my $sum2 = get_sum($i, $n2, \@opens);
my $mean = $sum2 / $n2;
my $std_deviation = get_deviation($i, $n2, $mean, \@opens);
push @upper_bound, $mid + $n3 * $std_deviation;
push @lower_bound, $mid - $n3 * $std_deviation;
}
for my $i (0 .. $#opens)
{
if(!defined($upper_bound[$i]))
{
push @res, 0;
next;
}
given( $opens[$i])
{
when($_ > $upper_bound[$i]) {push @res, 1; break}
when($_ < $lower_bound[$i]) {push @res, -1; break}
default {push @res, $res[-1]; break}
}
}
return \@res;
}
}
1;
and it's called like this:
my $klines_ref;
for my $n1 (1..200)
{
for my $n2 (1..200)
{
for my $n3 (1,3,5,7)
{
my $res = cal_using_simple_scheme($n1, $n2, $n3, $klines_ref);
#using the result to do something, omitted here.
}
}
}
$klines_ref is a reference to an array which contains at least 60000+
elements.
the module is simple, the main time consuming part is calculating sum and
standard deviation part. I cached the results for both sum and
std_deviation. but since the input array is so big that during the first
call of the cal_using_stupid_scheme the program crashes because of out of
memory. So I tie the two hashes to local files, and as I predicted, the
speed is unacceptable. maybe this is the kind of problem perl is good at?
I still use index because I really don't know how to avoid it. would some
body point out the wrong and not perlish part of the program above?
Thank you all.