我尝试使用Freebsd 12下的Perl版本5.20计算批量复制过程的传输速率。我得到了奇怪的结果,因为尽管使用了浮点除法来获得分形秒数,但亚秒间隔的值始终为零。持续时间条目。
详细信息:
为了进行测量,我使用DateTime :: Hires并在名为markTime
和diffTime
的两个子例程中抽象了时间标记和差异。要查看正在执行的每步操作,请打印。
#!/usr/bin/env perl
use v5.20.1;
use warnings;
use strict;
use bigint;
use Time::HiRes qw(usleep nanosleep);
use DateTime::HiRes;
use Scalar::Util::Numeric;
# Set the total size of an object
my $ttlSize = 1E3;
# Set the start time
my $startTime = &markTime('START');
# Sleep 12500 µs
usleep(12500);
# Calculate the elapsed time
my $runTime = &diffTime($startTime);
# Calculate the rate in Bytes per second
my $rate = $ttlSize/$runTime;
# Print it
print "RATE: $rate Bytes/s\n";
# Routine to set a timestamp
sub markTime () {
my $prefix = shift;
$prefix ='NOW' if not $prefix;
my $now = DateTime::HiRes->now;
print"MARK.$prefix: ",$now->strftime( '%Y-%m-%d-%H-%M-%S.%N' ),"\n";
return $now;
}
# Routine calc the difference
sub diffTime () {
my $start = shift;
# Calculate the duration
my $now = &markTime('DIFF');
my $dur = $now - $start;
my $nano = $dur->in_units('nanoseconds');
# Original dateTime duration is integer
print "DT.DUARTION: ",$nano," ns IS.INT: ",
Scalar::Util::Numeric::isint($nano),"\n";
# Calc values for mano, micro, milli and seconds
my $math_ns = sprintf("%e",$nano);
my $math_mus = sprintf("%e",$math_ns/1.0E3);
my $math_ms = sprintf("%e",$math_ns/1.0E6);
my $math_s = sprintf("%e",$math_ns/1.0E9);
# Show the calculations
print"MATH: ",$math_ns," ns\n";
print"MATH: ",$math_mus," µs\n";
print"MATH: ",$math_ms," ms\n";
print"MATH: ",$math_s," s\n";
# Check if the stuff ist float
print "TIME.SECS: ", $math_ns*1.0E-9,
" TIME.NANO: " ,$math_ns,
" IS.FLOAT: " ,Scalar::Util::Numeric::isfloat($math_ns),"\n";
return $math_s;
}
结果显示,尽管使用浮点除法运算,但runtime
的亚秒浮点值已被除法“截断”,并且传输速率变为INF。
MARK.START: 2019-12-12-10-12-33.954870000
MARK.DIFF: 2019-12-12-10-12-33.968422000
DT.DUARTION: 13552000 ns IS.INT: 1
MATH: 1.355200e+07 ns
MATH: 1.355200e+04 µs
MATH: 1.300000e+01 ms
MATH: 0.000000e+00 s
TIME.SECS: 0 TIME.NANO: 1.355200e+07 IS.FLOAT: 1
RATE: inf Bytes/s
为了获得$runtime
变量的正确值0.013552,我该怎么办?
转储值:
---NANO---
SV = PVNV(0x8029cf9f0) at 0x8031c6408
REFCNT = 1
FLAGS = (IOK,NOK,POK,IsCOW,pIOK,pNOK,pPOK)
IV = 13574000
NV = 13574000
PV = 0x8031ab5d0 "13574000"\0
CUR = 8
LEN = 10
COW_REFCNT = 1
---MATH_NS---
SV = PV(0x802cb8900) at 0x8031c64e0
REFCNT = 1
FLAGS = (POK,IsCOW,pPOK)
PV = 0x8031ab0f0 "1.357400e+07"\0
CUR = 12
LEN = 16
COW_REFCNT = 2
---MATH_NS/1E9---
SV = PV(0x802d18b50) at 0x802f19bb8
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x8031d97c8
SV = PVHV(0x800a8a560) at 0x8031d97c8
REFCNT = 2
FLAGS = (OBJECT,SHAREKEYS)
STASH = 0x8016910d8 "Math::BigInt"
ARRAY = 0x80323cdc0 (0:7, 2:1)
hash quality = 62.5%
KEYS = 2
FILL = 1
MAX = 7
Elt "value" HASH = 0x7025df17
SV = IV(0x803162b60) at 0x803162b70
REFCNT = 1
FLAGS = (ROK)
RV = 0x801acca08
SV = PVAV(0x800a894d8) at 0x801acca08
REFCNT = 1
FLAGS = (OBJECT)
STASH = 0x801692e70 "Math::BigInt::Calc"
ARRAY = 0x802d3bb18
FILL = 0
MAX = 0
FLAGS = (REAL)
Elt No. 0
SV = IV(0x800b19ae8) at 0x800b19af8
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 0
Elt "sign" HASH = 0xc9f40697
SV = PV(0x802cb8aa0) at 0x8031c6078
REFCNT = 1
FLAGS = (POK,IsCOW,pPOK)
PV = 0x8017af0f0 "+"\0
CUR = 1
LEN = 10
COW_REFCNT = 1
PV = 0x8031d97c8 ""
CUR = 0
LEN = 0
diffTime与Math :: BigFloat的校正
所以我弄清楚了,在程序use bigint;
中(现在在示例中被调用)是麻烦制造者,它将对所有部门产生影响。解决方法是:
sub diffTimeBigFloat () {
my $start = shift;
# Calculate the duration
my $now = &markTime('DIFF');
my $dur = $now->subtract_datetime_absolute($start);
my $nano = $dur->in_units('nanoseconds');
# Original dateTime Duration
print "DT.DUARTION: ",$nano," ns IS.INT: ",
Scalar::Util::Numeric::isint($nano),"\n";
# Calc values for mano, micro, milli and seconds
my $math_s = Math::BigFloat->new(sprintf("%sE-9",$nano));
print"MATH: ",$math_s," s\n";
print "TIME.SECS: ", $math_s,
" TIME.NANO: ", $math_s*1E9,
" IS.FLOAT: " ,Scalar::Util::Numeric::isfloat($math_s),"\n";
return $math_s;
}
[use bigint;
有效地导致1.0E9
替换为Math::BigInt->new(1.0E9)
。