在支持较好的测试机上直接运行RUN脚本即可得到测试结果
测试结果(部分)
BYTE UNIX Benchmarks (Version 5.1.3)
------------------------------------------------------------------------
Benchmark Run: Wed Aug 07 2024 17:02:28 - 17:30:33
8 CPUs in system; running 1 parallel copy of tests
Dhrystone 2 using register variables 57732243.9 lps (10.0 s, 7 samples)
Double-Precision Whetstone 9863.5 MWIPS (9.9 s, 7 samples)
Execl Throughput 270.8 lps (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks 2036.0 KBps (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks 492.0 KBps (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks 8573.2 KBps (30.0 s, 2 samples)
Pipe Throughput 3224999.0 lps (10.0 s, 7 samples)
Pipe-based Context Switching 10965.9 lps (10.0 s, 7 samples)
Process Creation 6449.4 lps (30.0 s, 2 samples)
Shell Scripts (1 concurrent) 1037.6 lpm (60.1 s, 2 samples)
Shell Scripts (8 concurrent) 559.1 lpm (60.1 s, 2 samples)
System Call Overhead 3044508.5 lps (10.0 s, 7 samples)
System Benchmarks Index Values BASELINE RESULT INDEX
Dhrystone 2 using register variables 116700.0 57732243.9 4947.1
Double-Precision Whetstone 55.0 9863.5 1793.4
Execl Throughput 43.0 270.8 63.0
File Copy 1024 bufsize 2000 maxblocks 3960.0 2036.0 5.1
File Copy 256 bufsize 500 maxblocks 1655.0 492.0 3.0
File Copy 4096 bufsize 8000 maxblocks 5800.0 8573.2 14.8
Pipe Throughput 12440.0 3224999.0 2592.4
Pipe-based Context Switching 4000.0 10965.9 27.4
Process Creation 126.0 6449.4 511.9
Shell Scripts (1 concurrent) 42.4 1037.6 244.7
Shell Scripts (8 concurrent) 6.0 559.1 931.9
System Call Overhead 15000.0 3044508.5 2029.7
========
System Benchmarks Index Score 189.4
------------------------------------------------------------------------
Benchmark Run: Wed Aug 07 2024 17:30:33 - 17:58:43
8 CPUs in system; running 8 parallel copies of tests
Dhrystone 2 using register variables 438641213.0 lps (10.0 s, 7 samples)
Double-Precision Whetstone 75079.1 MWIPS (9.7 s, 7 samples)
Execl Throughput 3092.1 lps (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks 19974.9 KBps (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks 5061.5 KBps (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks 75627.0 KBps (30.0 s, 2 samples)
Pipe Throughput 25578987.9 lps (10.0 s, 7 samples)
Pipe-based Context Switching 3692847.5 lps (10.0 s, 7 samples)
Process Creation 62683.6 lps (30.0 s, 2 samples)
Shell Scripts (1 concurrent) 4688.8 lpm (60.1 s, 2 samples)
Shell Scripts (8 concurrent) 822.1 lpm (60.2 s, 2 samples)
System Call Overhead 24022012.0 lps (10.0 s, 7 samples)
System Benchmarks Index Values BASELINE RESULT INDEX
Dhrystone 2 using register variables 116700.0 438641213.0 37587.1
Double-Precision Whetstone 55.0 75079.1 13650.7
Execl Throughput 43.0 3092.1 719.1
File Copy 1024 bufsize 2000 maxblocks 3960.0 19974.9 50.4
File Copy 256 bufsize 500 maxblocks 1655.0 5061.5 30.6
File Copy 4096 bufsize 8000 maxblocks 5800.0 75627.0 130.4
Pipe Throughput 12440.0 25578987.9 20561.9
Pipe-based Context Switching 4000.0 3692847.5 9232.1
Process Creation 126.0 62683.6 4974.9
Shell Scripts (1 concurrent) 42.4 4688.8 1105.8
Shell Scripts (8 concurrent) 6.0 822.1 1370.1
System Call Overhead 15000.0 24022012.0 16014.7
========
System Benchmarks Index Score 1858.7
需要重点关注的是RESULT INDEX
两列以及最终得分System Benchmarks Index Score
单进程测试(简化版shell代码)
###################### 单核测试 ##########################
echo "Dhrystone 2 using register variables"
./dhry2reg 10 # 结果除以10
echo "Double-Precision Whetstone"
./whetstone-double 10
# ./execl 30
echo "File Copy 1024 bufsize 2000 maxblocks"
./fstime -c -t 30 -d ../tmp/ -b 1024 -m 2000
echo "File Copy 256 bufsize 500 maxblocks"
./fstime -c -t 30 -d ../tmp/ -b 256 -m 500
echo "File Copy 4096 bufsize 8000 maxblocks"
./fstime -c -t 30 -d ../tmp/ -b 4096 -m 8000
echo "Pipe Throughput"
./pipe 10 # 结果除以10
echo "Pipe-based Context Switching"
./context1 10 # 结果除以10
echo "Process Creation"
./spawn 30 # 结果除以30
分数计算规则(源码解析)
sub indexResults {
my ( $results ) = @_;
# Read in the baseline result data. If we can't get it, just return
# without making indexed results.
my $index = readResultsFromFile($BINDIR . "/index.base");
if (!defined($index)) {
return;
}
# Count the number of results we have (indexed or not) in
# each category.
my $numCat = { };
foreach my $bench (@{$results->{'list'}}) {
my $bresult = $results->{$bench};
++$numCat->{$bresult->{'cat'}};
}
$results->{'numCat'} = $numCat;
my $numIndex = { };
my $indexed = { };
my $sum = { };
foreach my $bench (sort(keys(%$index))) {
# Get the test data for this benchmark.
my $tdata = $testParams->{$bench};
if (!defined($tdata)) {
abortRun("unknown benchmark \"$bench\" in $BINDIR/index.base");
}
# Get the test category. Count the total tests in this cat.
my $cat = $tdata->{'cat'};
++$numIndex->{$cat};
# If we don't have a result for this test, skip.
next if (!defined($results->{$bench}));
# Get the index and actual results. Calcluate the score.
my $iresult = $index->{$bench};
my $bresult = $results->{$bench};
my $ratio = $bresult->{'score'} / $iresult->{'score'};
# Save the indexed score.
$bresult->{'iscore'} = $iresult->{'score'};
$bresult->{'index'} = $ratio * 10;
# Sun the scores, and count this test for this category.
$sum->{$cat} += log($ratio) if ($ratio > 0.000001);
++$indexed->{$cat};
}
# Calculate the index scores per category.
$results->{'indexed'} = $indexed;
$results->{'numIndex'} = $numIndex;
foreach my $c (keys(%$indexed)) {
if ($indexed->{$c} > 0) {
$results->{'index'}{$c} = exp($sum->{$c} / $indexed->{$c}) * 10;
}
}
}
测试得到的RESULT 并不是最后的打分结果,这里需要进行基准矫正得分,UnixBench 对一台基准测试机器进行测试得到其性能结果(即BASELINE
那一列),并设定其分值为10,因此INDEX得分是RESULT / BASELINE * 10
最终的System Benchmarks Index Score
计算公式为:exp(sum(log(manycores_score_list))/total_test_nums)
其中manycores_score_list
表示RESULT
列的结果,total_test_nums
表示测试项数目,目前官方标准测试项目数为12
多进程测试相关代码
# Execute a benchmark command. We set off a given number of copies in
# parallel to exercise multiple CPUs.
#
# We return an array of results hashes, one per copy; each one is as
# returned by readResults().
sub executeBenchmark {
my ( $command, $copies ) = @_;
# Array of contexts for all the copies we're running.
my $ctxt = [ ];
# Kick off all the commands at once.
for (my $i = 0; $i < $copies; ++$i) {
my ( $cmdPid, $cmdFd ) = commandBuffered($command);
$ctxt->[$i] = {
'pid' => $cmdPid,
'fd' => $cmdFd,
};
}
# Now, we can simply read back the command results in order. Because
# the child processes read and buffer the results and time the commands,
# there's no need to use select() to read the results as they appear.
my $pres = [ ];
for (my $i = 0; $i < $copies; ++$i) {
my $presult = readResults($ctxt->[$i]{'pid'}, $ctxt->[$i]{'fd'});
push(@$pres, $presult);
}
$pres;
}
# Exec the given command in a sub-process.
#
# In the child process, we run the command and store its standard output.
# We also time its execution, and catch its exit status. We then write
# the command's output, plus lines containing the execution time and status,
# to a pipe.
#
# In the parent process, we immediately return an array containing the
# child PID and the filehandle to the pipe. This allows the caller to
# kick off multiple commands in parallel, then gather their output.
sub commandBuffered {
my ( $cmd ) = @_;
# Create a pipe for parent-child communication.
my $childReader;
my $parentWriter;
pipe($childReader, $parentWriter) || abortRun("pipe() failed");
$parentWriter->autoflush(1);
# Fork off the child process.
my $pid = fork();
if (!defined($pid)) {
abortRun("fork() failed (undef)");
} elsif ($pid == 0) {
# Close the other end of the pipe.
close $childReader;
# Start the clock and spawn the command.
my $benchStart = Time::HiRes::time();
my ( $cmdPid, $cmdFd ) = command($cmd);
# Read and buffer all the command's output.
my $output = [ ];
while (<$cmdFd>) {
push(@$output, $_);
}
# Stop the clock and save the time.
my $elTime = Time::HiRes::time() - $benchStart;
push(@$output, sprintf "elapsed|%f\n", $elTime);
# Wait for the child to die so we can get its status.
# close($cmdFd); Doesn't work???
waitpid($cmdPid, 0);
my $status = $?;
push(@$output, sprintf "status|%d\n", $status);
# Now that we've got the time, play back all the output to the pipe.
# The parent can read this at its leisure.
foreach my $line (@$output) {
print $parentWriter $line;
}
# Terminate this child.
close $parentWriter;
exit(0);
}
# Close the other end of the pipe.
close $parentWriter;
return ( $pid, $childReader );
}