通常而言大家普遍的认知里switch case的效率高于if else。根据我的理解而言switch的查找类似于二叉树,if则是线性查找。按照此逻辑推理对于对比条件数目大于3时switch更优,并且对比条件数目越多时switch的优势越为明显。




 



一、测试目的



最近与开发同学对于前面提到的性能问题,有着各自不同的见解,为证明我的观点,现设计如下测试场景验证

PS:一个方法里多达65个if else





二、测试策略

利用Junit4执行本次测试,分别设计50个、70个、100个条件式测试,每轮测试分别执行1千万、2千万、3千万、4千万、5千万和6千万次,为了力求让每轮测试不受外部因素干扰每轮测试执行10次收集信息分析。

为了让java在纯净的环境中运行。同时关闭了QQ、360、chrome等应用软件。 



三、测试环境



  • Java 版本信息



Java version "1.7.0_25"

Java(TM) SE Runtime Environment (build 1.7.0_25-b17)

Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)

Junit4



  • JVM配置信息



--launcher.XXMaxPermSize

256m

-Dosgi.requiredJavaVersion=1.6

-Xms512m

-Xmx1024m

  • 系统信息

Windows7 旗舰版

64位操作系统

  • 设备信息



处理器:Intel(R) Core(TM) i3-2328M CPU @ 2.20GHz 2.20 GHz

安装内存(RAM):4.00GB (3.90 GB 可用)

因此次不涉及硬盘读写,故不记录硬盘信息







四、测试脚本



        因篇幅所限,测试脚本略有缩减。


1        import java.util.Calendar; 
      
 2        import java.util.GregorianCalendar; 
      
 3        import java.util.Random; 
      
 4        import org.junit.After; 
      
 5        import org.junit.Before; 
      
 6        import org.junit.Test; 
      
 7        public  
      class ServerServiceTest { 
      
 8  Calendar calender_begin, calender_end;       
 9  Long time_begin, time_end;        // 
      记录测试开始时间,结束时间 
      
       10   
      int flagNumber = 1000000; 
      // 
       迭代数 
      
       11  Random r =  
      new Random(); 
      
12         int i =  
      new Random().nextInt(100); 
      // 
      生成随机种子 
      
       13  @Before 
      
14         public  
      void setUp()  
      throws Exception { 
      
15   calender_begin =        new GregorianCalendar(); 
      
16   time_begin = calender_begin.getTimeInMillis();       
17  }       
18  @After       
19         public  
      void tearDown()  
      throws Exception { 
      
20   calender_end =        new GregorianCalendar(); 
      
21   time_end = calender_end.getTimeInMillis();       
22   System.out.println(time_end - time_begin);       
23  }       
24  @Test       
25         public  
      void ifTest() { 
      
26          for ( 
      int temp = 0; temp < flagNumber; temp++) { 
      
27    i = r.nextInt(100);       
28           if (i == 0) { 
      
29    }        else  
      if (i == 1) { 
      
30    }        else  
      if (i == 2) { 
      
31    }        else  
      if (i == 3) { 
      
32    }        else  
      if (i == 4) { 
      
33    }        else  
      if (i == 5) { 
      
34    }        else  
      if (i == 6) { 
      
35    }        else  
      if (i == 7) { 
      
36    }        else  
      if (i == 8) { 
      
37    }        else  
      if (i == 9) { 
      
38    }        else  
      if (i == 10) { 
      
39    }        
40   }       
41  }       
42  @Test       
43         public  
      void switchTest()  
      throws InterruptedException { 
      
44          for ( 
      int temp = 0; temp < flagNumber; temp++) { 
      
45    i = r.nextInt(100);       
46           switch (i) { 
      
47           case 0: 
      
48            break; 
      
49           case 1: 
      
50            break; 
      
51           case 2: 
      
52            break; 
      
53           case 3: 
      
54            break; 
      
55           case 4: 
      
56            break; 
      
57           case 5: 
      
58            break; 
      
59           default: 
      
60            break; 
      
61    }       
62   }       
63  }       
64     View Code



五、测试结果


        以下是收集的测试数据, 时间单位毫秒(ms)。其实这种数据看起来很难看出问题所在。


条件式测试数

迭代数


1

(ms)

2

3

4

5

6

7

8

9

10

avg

max

min

100

6千万

if

469

466

474

455

477

478

466

460

464

483

469

483

455

switch

443

443

441

438

443

437

441

442

439

438

441

443

437

5千万

if

399

420

394

403

408

402

403

393

410

430

406

430

393

switch

367

374

370

366

374

382

381

376

373

397

376

397

366

4千万

if

344

325

326

359

320

325

324

319

319

328

329

359

319

switch

302

305

300

315

302

302

298

318

297

300

304

318

297

3千万

if

255

249

240

248

249

247

250

256

251

246

249

256

240

switch

228

232

227

231

230

229

227

231

228

231

229

232

227

2千万

if

211

177

183

182

181

172

174

170

175

178

180

211

170

switch

165

149

155

152

154

155

155

166

151

158

156

166

149

1千万

if

179

174

176

176

169

177

176

191

173

183

177

191

169

switch

152

156

167

161

158

151

161

161

159

161

159

167

151

70

6千万

if

424

416

440

437

427

419

417

411

416

429

424

440

411

switch

389

395

387

388

388

392

397

391

392

393

391

397

387

5千万

if

368

366

352

354

351

352

350

362

355

361

357

368

350

switch

327

327

326

324

328

327

324

323

330

325

326

330

323

4千万

if

321

300

295

293

284

283

281

335

276

281

295

335

276

switch

259

262

260

262

259

261

259

268

260

267

262

268

259

3千万

if

219

229

226

217

220

226

215

223

217

226

222

229

215

switch

199

197

203

199

199

199

197

200

200

197

199

203

197

2千万

if

149

158

152

155

177

159

159

158

161

150

158

177

149

switch

136

136

132

134

145

133

133

132

136

133

135

145

132

1千万

if

86

83

87

81

90

88

77

83

95

85

86

95

77

switch

65

67

67

67

68

71

67

68

68

68

68

71

65

50

6千万

if

374

361

363

363

362

364

376

366

372

373

367

376

361

switch

347

343

341

341

338

362

340

343

343

343

344

362

338

5千万

if

324

312

306

306

341

312

312

299

307

307

313

341

299

switch

289

287

285

283

291

288

290

288

290

281

287

291

281

4千万

if

287

247

251

252

265

247

248

256

252

256

256

287

247

switch

239

237

236

229

243

230

235

232

228

228

234

243

228

3千万

if

193

196

195

197

203

198

201

188

200

204

198

204

188

switch

184

178

181

175

173

172

176

184

193

174

179

193

172

2千万

if

128

129

133

145

133

139

139

130

131

143

135

145

128

switch

117

118

118

117

115

120

114

113

116

118

117

120

113

1千万

if

81

68

82

75

76

68

69

79

91

75

76

91

68

switch

60

57

60

60

59

65

59

62

61

60

60

65

57



六、测试结果分析


        纯数据的测试结果,很难进行分析,经过整理以后如下图:


        

java中switch中能用if java switch和if_java


 


         if-100为if执行100条件式测试数,switch-100为switch执行100条件式测试数;


        根据此图表结果,大家已经可能很清晰的看出 IfSwtich的性能对比结果了。但是如此细微的性能差异,实现了业务就行了,何必关注这种费心又麻烦的事呢?


        哈哈哈,性能测试更多时候,也是沟通问题,更是行政问题。




 


 


七、总结


        这次验证过程,其实就是一次简单的性能测试过程,也就是——需求挖掘->明确目的->设计策略->准备环境->脚本编写->收集数据->结果分析->测试报告。此处略去的报告内容,因为不需要什么报告了。哈哈哈!(大家懂的)


        就大量条件式的业务场景而言,除了利用switch以外,其实还可以用到枚举(enum)作为条件式,抽象每个判断式导向为函数式(function)。可能哪天我心情好会把利用enum优化的代码给放出来。


 



2015-8-23 15:17:18 跟新

策略模式+接口注入,写的是伪代码没有严格的语法规范,大家凑合着看。


interface Service{
	
	public void execute();

	public <T> T eval();
}


public class Strategy{

	private static Concrunthashmap<String,function> content = new Concrunthashmap<String,function>();

	public void register(String name,Clas<T> xxx){
		if(!content.has(name)){
			content.put(xxx);//这里隐去了反射生成对象的过程
		}
	}

	public void execute(String name){
		content.get(name).execute();
	}

	public void eval(String name){
		content.get(name).eval();
	}
}

class HelloServiceImpl implements Service{

	public void execute(){
		print "hello world";
	}

	public String eval(){
		return "hello world";
	}
}

class HiServiceImpl implements Service{

	public void execute(){
		print "hi world";
	}

	public String eval(){
		return "hi world";
	}
}