您好我使用 Data::Random
模块生成随机日期,但生成 1百万的样本数据非常慢。如何提高速度呢?这是我尝试过的代码。
#!/usr/bin/perl -w
use Data::Random qw(:all);
my $randDate_Start = '1900-01-01';
my $randDate_End = '2010-12-31';
open Outfile, ">", "D:/Test.txt";
for(0..1000000)
{
my $randDate = rand_date( min=>$randDate_Start, max=>$randDate_End);
print Outfile $randDate."\n";
}
close Outfile;
还有其他方法可以生成随机日期
答案 0 :(得分:2)
我建议使用Time::Piece
。
如下面的基准所示,它显示性能提高了6倍。
如果您缓存可能的日期值,您可以获得所有100万个值的即时结果:
#!/usr/bin/perl -w
use strict;
use warnings;
use autodie;
use Benchmark;
use Data::Random qw(:all);
use Time::Piece;
use Time::Seconds;
my $randDate_Start = '1900-01-01';
my $randDate_End = '2010-12-31';
my $tp_start = Time::Piece->strptime( "$randDate_Start 12:00:00", "%Y-%m-%d %T" );
my $tp_end = Time::Piece->strptime( "$randDate_End 12:00:00", "%Y-%m-%d %T" );
my $tp_days = ( $tp_end - $tp_start )->days;
my @tp_cached = map { ( $tp_start + ONE_DAY * $_ )->strftime('%Y-%m-%d') } ( 0 .. $tp_days );
# Compare Data Methods
timethese(
1_000_000,
{ 'Data::Random' => sub { rand_date( min => $randDate_Start, max => $randDate_End ) },
'Time::Piece' => sub { ( $tp_start + ONE_DAY * int rand $tp_days )->strftime('%Y-%m-%d') },
'Time::Piece (cached)' => sub { $tp_cached[ rand $tp_days ] },
}
);
输出:
Benchmark: timing 1000000 iterations of Data::Random, Time::Piece, Time::Piece (cached)...
Data::Random: 61 wallclock secs (60.20 usr + 0.07 sys = 60.27 CPU) @ 16592.00/s (n=1000000)
Time::Piece: 10 wallclock secs ( 9.95 usr + 0.01 sys = 9.96 CPU) @ 100401.61/s (n=1000000)
Time::Piece (cached): 0 wallclock secs ( 0.08 usr + 0.00 sys = 0.08 CPU) @ 12500000.00/s (n=1000000)
(warning: too few iterations for a reliable count)
答案 1 :(得分:1)
使用@Glenn推荐的第二种技术,没有任何优化
use 5.010;
use strict;
use warnings;
use Date::Calc qw(Delta_Days Add_Delta_Days);
#create an array for each day
my $numdays = Delta_Days(1900,1,1, 2010,12,31) + 1;
my @dates = map { sprintf("%d-%02d-%02d", Add_Delta_Days(1900,1,1, $_)) } 0..$numdays;
say $dates[ rand($numdays) ] for(1..100_000_000);
运行
$ time perl dat | wc -l
100000000
real 0m32.227s
user 0m31.439s
sys 0m1.159s
代表100_000_000
。 1百万是1.2秒......
答案 2 :(得分:0)
我首先要展开循环。您可能无法将其展开一百万次,但您可以展开大量次并循环少一些。这将有助于加快速度,因为它不必为下一个项目分支。我做了一个简短的测试,它的速度提高了5到10倍。这是我建议的100万循环(如果我的数学正确:))
# Declare the variable before the loop
my $randDate;
# Statement is what we want to execute a number of times
my $statement = "$randDate = rand_date( min=>$randDate_Start, max=>$randDate_End);print Outfile \$randDate.\"\\n\";"
# Replicate the statement 1000 times
$statement = $statement x 1000;
# Get the time we started (to the second)
my $start = time();
# Loop 1000 times to make a 1 million items
for(0..1000)
{
# Evaluate the 1000 statements
eval($statement);
}
# Determine the amount of time it took
my $diff = time() - $start;
# Print out the time
print "Time taken is: $diff\n";
当我这样做时,如果我循环一百万次,则需要107秒,如果我使用上述方法生成一百万个项目,则需要28秒。
如果速度不够,那么您可能需要制定例程来生成日期。考虑到范围,每年将有111年和365.25天,这将是40543日期的范围。这可以在开始时生成一次。您可以使用时间范围的每个日期创建一个数组。然后使用rand,你可以生成一个0到40543之间的数字。这将给你和索引到数组中选择日期。如果上面提供足够的加速,这比上面的工作多一点。