PerformancePack

From LeakonWiki

Jump to: navigation, search

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 倍。 这个测试数据很有参考价值。

Personal tools