PerformancePack
From LeakonWiki
Contents |
序言
今天搞一个数据存储程序,需要把数据转换成二进制存储。
在转换过程中,发现效率很低,不能满足需要。
经过反复测试和修改,总结了一些经验,记录在这里,以便日后查询。
后面是代码、测试和分析,请细心看,没有多复杂,但是可以得到不少经验。
程序代码
class BinaryData {
public static function TransArrToBinOld(&$arrInput) {
$arrBinStream = array();
foreach ((array)$arrInput as $decNum) {
$arrBinStream[] = pack('i', $decNum);
}
return implode('', $arrBinStream);
}
public static function TransArrToBin(&$arrInput) {
$arrBinStream = array();
$length = count($arrInput);
$loop = intval($length / 40);
$mod = $length % 40;
$k = key($arrInput);
for ($i = 0; $i < $loop; ++$i) {
$arrBinStream[] = pack('i*',
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++],
$arrInput[$k++],$arrInput[$k++]
); // End of Pack
}
while ($mod-- > 0) {
$arrBinStream[] = pack('i', $arrInput[$k++]);
}
return implode('', $arrBinStream);
}
public static function TransBinToArr(&$binStream) {
return unpack('i*', $binStream);
}
}
测试代码
$arrHistory = array();
for ($i = 0; $i < 125000; $i++) {
$arrHistory[$i] = rand(0, 999999999);
}
echo "\n-------\nBegin\n";
$timeBegin = time();
for ($j = 0; $j < 1000; $j++) {
# $tmpBin = BinaryData::TransArrToBinOld($arrHistory);
$tmpBin = BinaryData::TransArrToBin($arrHistory);
echo '.';
}
$timeEnd = time();
$i = 1;
echo "\nExecute " . ($i * $j) . " times, use " . ($timeEnd - $timeBegin) . " seconds.\n";
echo "\nPerformance: " . intval(($i * $j) / ($timeEnd - $timeBegin)) . "/s \n";
测试成绩
分别在服务器和台式机上做测试
服务器
TransArrToBinOld: Execute 1000 times, use 194 seconds. Performance: 5/s
TransArrToBin: Execute 1000 times, use 51 seconds. Performance: 19/s
台式机
TransArrToBinOld: Execute 1000 times, use 328 seconds. Performance: 3/s
TransArrToBin: Execute 1000 times, use 89 seconds. Performance: 11/s
代码分析
通过测试,可以看出,程序的瓶颈就在 pack() 函数,这个函数的执行开销比较大。 pack() 是可以传入多个参数的,如果加长参数列表,减少循环次数,可以大大减少程序运行时间。
TransArrToBinOld 比 TransArrToBin 多运行了 40 倍次数的 pack(),运行时间是后者的 4 倍。 这个测试数据很有参考价值。

