关于 in_array 和 switch 的比较

该文章根据 CC-BY-4.0 协议发表,转载请遵循该协议。
本文地址:https://fenying.net/post/2015/06/17/performance-between-in-array-and-switch-in-php/

很多时候会用 in_array 判断一个值是否在允许值内,比如 in_array (‘apple’, $fruits) 就可以判断是否水果。

理论上这一点也可以用 switch 实现,但是问题就在于,switch 并不是可以随意改动的,而数组可以存放到配置文件里。而且另一个问题在于,尽管不如 in_array 方便,可 switch 是语言结构的一部分,性能上绝对比 in_array 高得多。而优化的条件就取决于,两者的性能差异有多大,如果不大,那么用 switch 对 in_array 进行优化毫无意义。

今天被人问到了,索性写一个程序试试两者的性能差异,如下。

 1<?php
 2/**
 3 *   This scripts is used to compare the speed
 4 * between in_array and switch.
 5 *
 6 * Author:    Angus.Fenying
 7 * Date:      2015-06-17
 8 * Blog:      http://fenying.blog.163.com
 9 */
10class Test {
11
12	public function main(array $args) {
13		set_time_limit(0);
14
15		/* 空白对照,只进行计数计时。*/
16
17		$time_blank = [];
18		for ($i = 0; $i < 10; ++$i)
19			$time_blank[] = $this->test_blank($i);
20		$time_blank = array_sum($time_blank) / count($time_blank);
21
22		/* 测试当 in_array 命中时的速度 */
23
24		$time_in_array_hit = [];
25		for ($i = 0; $i < 10; ++$i)
26			$time_in_array_hit[] = $this->test_in_array($i);
27		$time_in_array_hit = array_sum($time_in_array_hit) / count($time_in_array_hit);
28
29		/* 测试当 in_array 未命中时的速度 */
30
31		$time_in_array_miss = [];
32		for ($i = 5; $i < 10; ++$i)
33			$time_in_array_miss[] = $this->test_in_array($i);
34		$time_in_array_miss = array_sum($time_in_array_miss) / count($time_in_array_miss);
35
36		/* 测试当 switch 命中时的速度 */
37
38		$time_switch_hit = [];
39		for ($i = 0; $i < 10; ++$i)
40			$time_switch_hit[] = $this->test_switch($i);
41		$time_switch_hit = array_sum($time_switch_hit) / count($time_switch_hit);
42
43		/* 测试当 switch 未命中时的速度 */
44
45		$time_switch_miss = [];
46		for ($i = 5; $i < 10; ++$i)
47			$time_switch_miss[] = $this->test_switch($i);
48		$time_switch_miss = array_sum($time_switch_miss) / count($time_switch_miss);
49
50		echo '<p>Blank: ', $time_blank, '</p>';
51		echo '<p>in_array[hit]: ', $time_in_array_hit, '</p>';
52		echo '<p>in_array[miss]: ', $time_in_array_miss, '</p>';
53		echo '<p>switch[hit]: ', $time_switch_hit, '</p>';
54		echo '<p>switch[miss]: ', $time_switch_miss, '</p>';
55	}
56
57	protected function test_blank($g) {
58		$t0 = microtime(true);
59		for ($k = 0; $k < 1000000;++$k);
60		return microtime(true) - $t0;
61	}
62
63	protected function test_in_array($g) {
64		$t0 = microtime(true);
65		for ($k = 0; $k < 1000000;++$k)
66			if (in_array($k, [0,1,2,3,4]));
67			else;
68
69		return microtime(true) - $t0;
70	}
71
72	protected function test_switch($g) {
73		$t0 = microtime(true);
74		for ($k = 0; $k < 1000000;++$k)
75			switch ($g) {
76			case 0:
77			case 1:
78			case 2:
79			case 3:
80			case 4:
81				break;
82			default:
83			}
84
85		return microtime(true) - $t0;
86	}
87}

也就是进行10次 “100W次 in_array/switch 测试” ,然后求平均用时,个人的机器上测试结果是

  • 软件:Windows 8.1 Enterprise Edition / PHP 5.5.15 / Nginx 1.7.2
  • 硬件:Intel Core i5-3210M 2.5GHz / 8GB
  • 空白测试: 0.068772172927856
  • in_array[命中]: 1.4430939435959
  • in_array[未命中]: 1.4188071727753
  • switch[命中]: 0.24772312641144
  • switch[未命中]: 0.28292064666748

可见,switch 的效率大约是 in_array 的 5~6 倍。是否有价值对此进行优化,还请自酌~

comments powered by Disqus