TL;DR
Speed(KiB/s) = 解压大小(B) * 重复次数(#)/time(s) /1024(B/KiB)
usage(%) ≈ 程序占用 CPU 时间/程序开始到现在为止总耗时*100%
R/U(MIPS) ≈ 产生的指令数(MI)/占用 CPU 的时间
Rating(MIPS) ≈ 产生的指令数(MI)/程序耗时(s)
7zr b -mmt1
Compressing | Decompressing
Dict Speed Usage R/U Rating | Speed Usage R/U Rating
KiB/s % MIPS MIPS | KiB/s % MIPS MIPS
22: 4515 100 4403 4393 | 51373 100 4395 4386
23: 3883 100 3966 3956 | 50676 100 4395 4387
24: 3724 100 4014 4004 | 48750 100 4292 4280
25: 3520 100 4032 4020 | 48064 100 4293 4278
---------------------------------- | ------------------------------
Avr: 100 4104 4093 | 100 4344 4333
Tot: 100 4224 4213
Speed
这段打印在
//p7zip-17.05/CPP/7zip/UI/Common/Bench.cpp
static void PrintResults(IBenchPrintCallback *f,
const CBenchInfo &info,
unsigned weight,
,
UInt64 ratingbool showFreq, UInt64 cpuFreq,
*res)
CTotalBenchRes {
= info.GetSpeed(info.UnpackSize * info.NumIterations);
UInt64 speed if (f)
{
if (speed != 0)
(*f, speed / 1024, kFieldSize_Speed);
PrintNumberelse
(*f, 1 + kFieldSize_Speed);
PrintSpaces}
= info.GetUsage();
UInt64 usage = info.GetRatingPerUsage(rating);
UInt64 rpu if (f)
{
(*f, usage, rpu, rating, showFreq, cpuFreq);
PrintResults}
if (res)
{
// res->NumIterations1++;
->NumIterations2 += weight;
res->RPU += (rpu * weight);
res->Rating += (rating * weight);
res->Usage += (usage * weight);
res}
}
其中 info.GetSpeed()
如下:
//p7zip-17.05/CPP/7zip/UI/Common/Bench.cpp
static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
{
= elapsedTime;
UInt64 elTime (freq, elTime);
NormalizeValsif (elTime == 0)
= 1;
elTime return value * freq / elTime;
/*
* 原始公式: value /(elTime/freq)
* 各个变量对应的单位,其中:
* * value: number
* * elTime: ms
* * freq: ms/s ( or to say: 一秒内有多少个 ms event )
*/
}
::GetSpeed(UInt64 numCommands) const
UInt64 CBenchInfo{
return MyMultDiv64(numCommands, GlobalTime, GlobalFreq);
}
我们可以知道变量 speed 的定义如下:
speed(B/s) = 解压大小(B) * info.NumIterations(#)/time(s)
所以 Speed 列就是 Speed(KiB/s)=speed(B/s)/1024(B/KiB)
。即
Speed(KiB/s)=解压大小(B) * 重复次数(#)/time(s) /1024(B/KiB)
Usage, R/U, Rating
继续看剩下三列的定义:Usage, R/U, Rating
//p7zip-17.05/CPP/7zip/UI/Common/Bench.cpp
static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating, bool showFreq, UInt64 cpuFreq)
{
(f, (usage + 5000) / 10000, kFieldSize_Usage);
PrintNumber(f, rpu, kFieldSize_RU);
PrintRating(f, rating, kFieldSize_Rating);
PrintRatingif (showFreq)
{
if (cpuFreq == 0)
(f, kFieldSize_EUAndEffec);
PrintSpaceselse
{
= cpuFreq * usage / 100;
UInt64 ddd if (ddd == 0)
= 1;
ddd (f, (rating * 10000), ddd, kFieldSize_EU);
PrintPercents(f, rating, cpuFreq, kFieldSize_Effec);
PrintPercents}
}
}
Usage
usage
是从上一级 PrintResults
中通过
info.GetUsage()
取到的。简单跟踪之后可知:
usage = 程序占用 CPU 时间/程序开始到现在为止总耗时 * 10^6
其中 10^6
会在后续被除以 10000
规整为百分比。
本级的 PrintResults
中打印了 Usage
列,打印的时间是:(usage + 5000) / 10000
,除以
10000
就是上面说的“规整为百分比”,而加的 50%
大概是其他消耗占程序的 50%。总之,Usage
列大概指的是压缩测试占用 CPU
的百分比。即:usage(%) ≈ 程序占用 CPU 时间/程序开始到现在为止总耗时*100%
Rating
rating
是从以下代码得来的:
::GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size)
UInt64 CBenchProps{
if (dictSize < (1 << kBenchMinDicLogSize))
= (1 << kBenchMinDicLogSize);
dictSize = EncComplex;
UInt64 encComplex if (LzmaRatingMode)
{
= GetLogSize(dictSize) - (kBenchMinDicLogSize << kSubBits);
UInt64 t = 870 + ((t * t * 5) >> (2 * kSubBits));
encComplex }
= (UInt64)size * encComplex;
UInt64 numCommands
/*
* 和计算 Usage 时差不多,大概意思是:
* numCommands/elapsedTime
* 通过各种 size 估算出计算的 command 的数量是多少,单位是 Million Instruction (因为后面没见到除以 1,000,000)
*/
return MyMultDiv64(numCommands, elapsedTime, freq);
}
::SetEncodeResult(const CBenchInfo &info, bool final)
HRESULT CBenchCallbackToPrint{
(_file->CheckBreak());
RINOKif (final)
{
= BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize * info.NumIterations);
UInt64 rating (_file, info,
PrintResults, rating,
EncodeWeight, CpuFreq, &EncodeRes);
ShowFreqif (!Use2Columns)
->NewLine();
_file}
return S_OK;
}
所以 Rating
就是在“程序耗时”(Eltime
)期间,产生的指令数,单位:(MI/s)
即 MIPS
。即
R/U(MIPS) ≈ 产生的指令数(MI)/占用 CPU 的时间
R/U
(这也是我找这段代码的关键字)
可以看到 R/U
列来自变量
rpu
,rpu
来自变量 rating
,
简单跟踪之后发现,它和 Rating
的区别在于,将耗时改成了“占用 CPU 的时间”,所以也可以猜出
rpu
的缩写是 rating per usage,它的单位一样是(MI/s) 即
MIPS
。即
Rating(MIPS) ≈ 产生的指令数(MI)/程序耗时(s)