#!/usr/local/bin/perl
use
vars
qw($Size %cache %count_cache)
;
$Size
= 5000;
$| = 1;
sub
report {
my
(
$desc
,
$count
,
$sub
) =
@_
;
my
$timed
= timestr(timeit(
$count
,
$sub
));
$timed
=~ /([\d\.]+\s+cpu)/i;
printf
(
"%-65.65s %s\n"
,
"[ timing ] $desc"
, $1);
}
sub
test {
my
(
$desc
,
$eval
) =
@_
;
my
$result
=
eval
{
&$eval
} ?
"OK"
:
"ERROR - $@"
;
print
"$result ... $desc\n"
;
}
tie
%cache
,
'Tie::Cache'
, {
Debug
=> 0,
MaxCount
=>
$Size
,
MaxSize
=> 1000,
MaxBytes
=> 5000000,
};
tie
%count_cache
,
'Tie::Cache'
,
$Size
;
my
%normal
;
print
"++++ Benchmarking operations on Tie::Cache of size $Size\n\n"
;
my
$i
= 0;
report(
"insert of $Size elements into normal %hash"
,
$Size
,
sub
{
$normal
{++
$i
} =
$i
}
);
$i
= 0;
report(
"insert of $Size elements into MaxCount Tie::Cache"
,
$Size
,
sub
{
$count_cache
{++
$i
} =
$i
}
);
$i
= 0;
report(
"insert of $Size elements into MaxBytes Tie::Cache"
,
$Size
,
sub
{
$cache
{++
$i
} =
$i
}
);
my
$rv
;
$i
= 0;
report(
"reading $Size elements from normal %hash"
,
$Size
,
sub
{
$rv
=
$normal
{++
$i
} } );
$i
= 0;
report(
"reading $Size elements from MaxCount Tie::Cache"
,
$Size
,
sub
{
$rv
=
$count_cache
{++
$i
} } );
$i
= 0;
report(
"reading $Size elements from MaxBytes Tie::Cache"
,
$Size
,
sub
{
$rv
=
$cache
{++
$i
} } );
$i
= 0;
report(
"deleting $Size elements from normal %hash"
,
$Size
,
sub
{
$rv
=
delete
$normal
{++
$i
} } );
$i
= 0;
report(
"deleting $Size elements from MaxCount Tie::Cache"
,
$Size
,
sub
{
$rv
=
delete
$count_cache
{++
$i
} }
);
report(
"deleting $Size elements from MaxBytes Tie::Cache"
,
$Size
,
sub
{
$rv
=
delete
$cache
{++
$i
} }
);
my
$over
=
$Size
* 2;
$i
= 0;
%cache
= ();
report(
"$over inserts overflowing MaxBytes Tie::Cache"
,
$over
,
sub
{
$cache
{++
$i
} =
$i
; }
);
$i
= 0;
report(
"$over reads from overflowed MaxBytes Tie::Cache"
,
$over
,
sub
{
$cache
{++
$i
} }
);
report(
"$over undef inserts, not affecting MaxBytes Tie::Cache"
,
$over
,
sub
{
$cache
{
rand
()} =
undef
; }
);
report(
"$over undef reads, not affecting MaxBytes Tie::Cache"
,
$over
,
sub
{
$cache
{
rand
()}; }
);
print
"\n++++ Testing for correctness\n\n"
;
my
@keys
=
keys
%cache
;
test(
"number of keys in %cache = $Size"
,
sub
{
@keys
==
$Size
}
);
test(
"first key in %cache = "
.(
$Size
+ 1),
sub
{
$keys
[0] ==
$Size
+ 1 }
);
test(
"last key in %cache = "
.(
$Size
+
$Size
),
sub
{
$keys
[
$#keys
] ==
$Size
+
$Size
}
);
test(
"first key value in %cache = "
.(
$Size
+ 1),
sub
{
$cache
{
$keys
[0]} ==
$Size
+ 1 }
);
delete
$cache
{
$keys
[0]};
test(
"deleting key $keys[0]; no value defined for deleted key"
,
sub
{ !
defined
$cache
{
$keys
[0]} }
);
test(
"existance of deleted key = ! exists"
,
sub
{ !
exists
$cache
{
$Size
+1} }
);
@keys
=
keys
%cache
;
test(
"first key in %cache after delete = "
.(
$Size
+ 2),
sub
{
$keys
[0] ==
$Size
+ 2 }
);
test(
"keys in cache after delete = "
.(
$Size
-1),
sub
{
keys
%cache
==
$Size
- 1 }
);
test(
"array type insert/read on MaxBytes cache"
,
sub
{
$cache
{
'array'
} = [
"test"
];
$cache
{
'array'
}->[0] eq
"test"
}
);
test(
"string type called ARRAY insert/read on MaxBytes cache"
,
sub
{
$cache
{
'array-fake'
} =
"ARRAY"
;
$cache
{
'array-fake'
} eq
"ARRAY"
}
);
test(
"hash type insert/read on MaxBytes cache"
,
sub
{
$cache
{
'array'
} = {
'foo'
=>
'bar'
};
$cache
{
'array'
}->{
'foo'
} eq
"bar"
}
);
exit
;
print
"\n++++ Stats for %cache\n\n"
;
my
$obj
=
tied
(
%cache
);
print
join
(
"\n"
,
map
{
"$_:\t$obj->{$_}"
}
'count'
,
'hit'
,
'miss'
,
'bytes'
);
print
"\n"
;
@ISA
=
qw(Tie::Cache)
;
my
(
$read_count
,
$write_count
) = (0,0);
sub
read
{
my
(
$self
,
$key
) =
@_
;
$read_count
++;
rand
() *
$key
;
}
sub
write
{
my
(
$self
,
$key
,
$value
) =
@_
;
$write_count
++;
}
print
"\n++++ Testing TRUE CACHE ++++\n\n"
;
my
$cache_size
= 100;
my
%cache
;
tie
%cache
,
'My::Cache'
, {
MaxBytes
=>
$cache_size
* 1000,
MaxCount
=>
$cache_size
,
Debug
=> 0,
WriteSync
=> 0,
};
&main::test
(
"read count == 0 pre reads"
,
sub
{
$read_count
== 0 });
my
$count
= 0;
for
(1..
$cache_size
) {
my
$value
=
$cache
{
$_
};
}
&main::test
(
"read count == $cache_size post reads"
,
sub
{
$read_count
==
$cache_size
});
for
(1..
$cache_size
) {
my
$new_value
=
int
(
rand
() * 10);
$cache
{
$_
} =
$new_value
;
}
&main::test
(
"write count == 0 pre flush()"
,
sub
{
$write_count
== 0 });
tied
(
%cache
)->flush();
&main::test
(
"write count == $cache_size post flush()"
,
sub
{
$write_count
==
$cache_size
});
%cache
= ();
&main::test
(
"write count == $cache_size post CLEAR()"
,
sub
{
$write_count
==
$cache_size
});
undef
%cache
;
print
"\n"
;
exit
;