ECharts源码分析优化

来源:互联网 发布:淘宝网品牌女裤 编辑:程序博客网 时间:2024/05/17 03:36

一、内存优化的原因及解决方案

ECharts在现代浏览器(IE9+、Chrome)下长时间使用,内存的变化并不特别明显。但在IE 8 或以下浏览器长期使用时,则出现内存不断增大的情况。其主要原因是ECharts不同浏览器下实现canvas的代码不一样所指。ECharts在不支持HTML 5的浏览器中,使用Google在06年开发的Explorer Canvas(简称excanvas),模拟canvas功能,而在支持HTML 5的浏览器中,则采用轻量级图表插件Zender插件实现核心功能。由于excanvas是在06年编写的,已经很久没有更新及维护,在JS方面,很多思想已经不符合ECMAScript 5的规定,也没有针对IE的内存回收机制进行优化。
另外由于IE的内存回收机制分为JavaScript变量回收机制和DOM变量计数回收机制,一旦将js变量与DOM变量混合使用,IE则容易无法自动回收,造成内存泄漏,需要手动清理变量。
在ECharts中是有API手动清理变量的,分别是clear和dispose,区别是前者只需插入参数,ECharts就会重绘图表;而后者则是直接将ECharts对象进行清理,需要重新构建ECharts对象。
另外,IE也有自身的回收内存函数CollectGarbage,每次浏览器最小化的时候,浏览器都会调用该函数,清理内存。
下面,将组合调用以上函数,对ECharts进行内存优化。

二、测试

在本次测试中,共有15组测试。其中对照测试组1和10。利用函数clear清理内存的测试组有2、3、4、8、9、11、12、13、14、16;利用dispose的有5、7、15,除1-4组外,均结合IE的CollectGarbage(简称CG)进行测试。见表1或图1。

新增测试组202122,是基于单个图表进行,使用ajax从后台获取随机生产的数据,对照测试组为测试111


表1 测试组及测试内容

测试组

测试内存

1

对照测试组,仅使用setSeries更新数据

2

使用clear后,再setSeries更新数据

3

使用clear后,再setSeries更新数据(10个表单)

4

使用clear后,再setSeries更新数据(10个表单,与测试3对比)

5

使用dispose,每20ms使用CollectGarbage清理内存(10个表单)

重写JavaScript闭包

7

使用dispose,每20ms使用CollectGarbage清理内存(10个表单,与测试5对比)

8

使用clear后,再setOption更新数据,每20ms使用CollectGarbage清理内存(10个表单)

9

继承测试8条件,每1分钟使用CollectGarbage清理内存(10个表单)

10

使用setSeries更新数据,每1分钟使用CollectGarbage清理内存(10个表单)

11

继承测试9条件,每30秒使用CollectGarbage清理内存(10个表单)

12

继承测试9条件,每45秒使用CollectGarbage清理内存(10个表单)

13

继承测试9条件,每15秒使用CollectGarbage清理内存(10个表单)

14

继承测试9条件,每7.5秒使用CollectGarbage清理内存(10个表单)

15

使用dispose,每22.5秒使用CollectGarbage清理内存(10个表单,与测试5对比)

16

继承测试9条件,每22.5秒使用CollectGarbage清理内存(10个表单)

20

基于测试11,将刷新时间改为5秒,并将图表个数改为1

21

基于测试20,将CG功能移到更新数据函数内,CG时间改为5秒

22

基于测试20,将CG的时间改为5秒

将测试时间由时间变化时间改为CPU运行时间,数据可能会变大

25

基于测试20,将CG的时间改为10秒

26

基于测试26,将CG的时间改为15秒

27

基于测试27,将CG的时间改为20秒





图1 测试组及测试内容


测试1

测试内容,每50ms更新一次图表数据。.
动态更新数据关键代码:            myChart.setSeries([                {                    "name": "销量",                    "type": "bar",                    "data": dataset  //数据                }            ]);

测试结果:

动作

内存(KB)

CPU(%)

刷新次数

对应时间(天)

内存变化(MB)

打开浏览器

线程1

线程2

18952

15456

100

0

打开网页

49152

16228

100

29.49

1分钟后

58604

3376

100

1200

2.5

38.72

5分钟后

71808

3888

100

6000

12.5

51.62

10分钟后

84480

3900

100

12000

25

63.99

20分钟后

115700

4020

100

24000

50

94.48

30分钟后

136520

4020

100

36000

75

114.81

1小时后

200680

4020

100

72000

150

177.47

2小时后

4020

100

144000

300

IE奔溃

441380

1492

100

242400

505

412.53


测试2

加入每次更新数据前调用clear方法,测试结果:

动作

内存(KB)

CPU(%)

刷新次数

对应时间(天)

内存变化(MB)

打开网页

51476

100

-

-

0

2分钟后

51628

100

2400

5

0.15

5分钟后

52408

100

6000

12.5

0.91

10分钟后

52968

100

12000

25

1.46

20分钟后

53084

68

24000

50

1.57

30分钟后

53544

60

36000

75

2.02

1小时后

54488

78

72000

150

2.94

2小时后

IE奔溃

-

144000

300

-



测试3、4

为了让测试效果更加明显,让页面同时加载10个图表,测试结果:

动作

内存(KB)

CPU(%)

刷新次数

对应时间(天)

内存变化(MB)

打开网页

166404

-

100

-

-

0

2分钟后

171420

4.9

100

2400

5

4.9

6分钟后

173048

6.49

100

7200

15

6.49

10分钟后

174096

7.51

100

12000

25

7.51

20分钟后

177616

10.95

100

24000

50

10.95

30分钟后

180212

13.48

100

36000

75

13.48


动作

内存(KB)

CPU(%)

刷新次数

对应时间(天)

内存变化(MB)

打开网页

145604

100

-

-

0

1分钟后

145208

100

1200

3

-0.39

4分钟后

141896

100

4800

10

-3.62

15分钟后

147248

100

18000

38

1.61

19分钟后

144032

100

22800

48

-1.54

28分钟后

144728

100

33600

70

-0.86

35分钟后

153500

100

42000

88

7.71

39分钟后

143756

100

46800

98

-1.8

43分钟后

144596

100

51600

108

-0.98

57分钟后

144820

100

68400

143

-0.77


测试5、7

使用dispose和IE特有的CollectGarbage函数每50ms清理内存,核心代码:           myChart.dispose();//销毁对象并设为null           dataset.splice(0, dataset.length);           window.CollectGarbage && CollectGarbage();//清理内存……           myChart = echarts.init(document.getElementById(id));           myChart.setOption(option);

动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

128008

-

-

0

7分钟

0.1小时

134168

8400

17.5

6.02

10分钟

0.2小时

135456

12000

25

7.27

20分钟

0.3小时

135984

24000

50

7.79

33分钟

0.6小时

141484

39600

82.5

13.16

75分钟

1.3小时

177220

90000

187.5

48.06

93分钟

1.6小时

155208

111600

232.5

26.56

104分钟

1.7小时

155392

124800

260

26.74

128分钟

2.1小时

160384

153600

320

31.62

139分钟

2.3小时

160096

166800

347.5

31.34

158分钟

2.6小时

159254

189600

395

30.51

181分钟

3小时

167508

217200

452.5

38.57

202分钟

3.4小时

179708

242400

505

50.49

216分钟

3.6小时

180512

259200

540

51.27

687分钟

11.5小时

363228

824400

1717.5

229.71

694分钟

11.6小时

366960

832800

1735

233.35


动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

打开网页

-

138684

-

-

-

18分钟后

0.3小时

142956

21600

45

4.17

23分钟后

0.4小时

144072

27600

57.5

5.26

45分钟后

0.8小时

144262

54000

112.5

5.45

62分钟后

1小时

149488

74400

155

10.55

67分钟后

1.1小时

153732

80400

167.5

14.7

80分钟后

1.3小时

156844

96000

200

17.73

95分钟后

1.6小时

159116

114000

237.5

19.95

133分钟后

2.2小时

169820

159600

332.5

30.41

239分钟后

4小时

201396

286800

597.5

61.24

268分钟后

4.5小时

222172

321600

670

81.53

340分钟后

5.7小时

242028

408000

850

100.92


测试8

使用clear和CollectGarbage函数每50ms清理内存,核心代码:           myChart.clear();dataset.splice(0, dataset.length);           window.CollectGarbage && CollectGarbage();//清理内存……           myChart.setOption(option);


动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

打开网页

-

140092

-

-

-

4分钟后

0.1小时

142512

4800

10

2.36

13分钟后

0.2小时

142440

15600

32.5

2.29

28分钟后

0.5小时

150832

33600

70

10.49

66分钟后

1.1小时

156800

79200

165

16.32

172分钟后

2.9小时

166964

206400

430

26.24

201分钟后

3.4小时

165852

241200

502.5

25.16

272分钟后

4.5小时

175892

326400

680

34.96

285分钟后

4.8小时

180336

342000

712.5

39.3

296分钟后

4.9小时

185152

355200

740

44


测试9

将CG调到更新数据函数外,改为每1分钟清理一次内存,核心代码:            if (window.CollectGarbage) {                setInterval(function () {                    CollectGarbage();                }, 60000);            }

动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

打开网页

-

137864

-

-

-

5分钟后

0.1小时

147512

6000

12.5

9.42

7分钟后

0.1小时

145212

8400

17.5

7.18

20分钟后

0.3小时

158152

24000

50

19.81

39分钟后

0.7小时

164448

46800

97.5

25.96

67分钟后

1.1小时

159164

80400

167.5

20.8

83分钟后

1.4小时

156324

99600

207.5

18.03

99分钟后

1.7小时

156452

118800

247.5

18.15

110分钟后

1.8小时

152448

132000

275

14.24

130分钟后

2.2小时

171844

156000

325

33.18

150分钟后

2.5小时

157180

180000

375

18.86

365分钟后

6.1小时

178444

438000

912.5

39.63

451分钟后

7.5小时

188632

541200

1127.5

49.58

465分钟后

7.8小时

182888

558000

1162.5

43.97

994分钟后

16.6小时

302516

1192800

2485

160.79



测试10

本测试为对照测试组,测试仅使用每50ms清理一次内存的内存变化情况,测试结果:

动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

0分钟后

-

140648

-

-

-

19分钟后

0.3小时

188640

22800

47.5

46.87

32分钟后

0.5小时

202072

38400

80

59.98

43分钟后

0.7小时

216880

51600

107.5

74.45



测试11

与测试9代码一样,将CG的时间改为30秒,测试结果:

动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

打开网页

-

132444

-

-

-

155分钟后

2.6小时

135904

186000

387.5

3.38

166分钟后

2.8小时

137964

199200

415

5.39

187分钟后

3.1小时

140060

224400

467.5

7.44

403分钟后

6.7小时

141304

483600

1007.5

8.65

488分钟后

8.1小时

151900

585600

1220

19

502分钟后

8.4小时

151740

602400

1255

18.84

615分钟后

10.3小时

160150

738000

1537.5

27.06



测试12

与测试9代码一样,将CG的时间改为45秒,测试结果:

动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

打开网页

0小时

137016

0

-

-

4分钟后

0.1小时

139488

4800

10

2.41

9分钟后

0.2小时

141924

10800

22.5

4.79

16分钟后

0.3小时

149020

19200

40

11.72

32分钟后

0.5小时

146200

38400

80

8.97

61分钟后

1小时

156444

73200

152.5

18.97

78分钟后

1.3小时

166616

93600

195

28.91

114分钟后

1.9小时

179388

136800

285

41.38



测试13

与测试9代码一样,将CG的时间改为15秒,测试结果:

动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

打开网页

-

136488

-

-

-

3分钟后

0.1小时

147712

3600

7.5

10.96

10分钟后

0.2小时

145888

12000

25

9.18

27分钟后

0.5小时

145776

32400

67.5

9.07

56分钟后

0.9小时

148502

67200

140

11.73

74分钟后

1.2小时

146772

88800

185

10.04

109分钟后

1.8小时

154544

130800

272.5

17.63

118分钟后

2小时

158112

141600

295

21.12

184分钟后

3.1小时

157120

220800

460

20.15

275分钟后

4.6小时

157044

330000

687.5

20.07

327分钟后

5.5小时

157032

392400

817.5

20.06

364分钟后

6.1小时

160172

436800

910

23.13

416分钟后

6.9小时

164528

499200

1040

27.38

491分钟后

8.2小时

184292

589200

1227.5

46.68

508分钟后

8.5小时

185900

609600

1270

48.25


测试14

与测试9代码一样,将CG的时间改为7.5秒,测试结果:

动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

打开网页

-

131876

-

-

-

66分钟后

1.1小时

134192

79200

165

2.26

75分钟后

1.3小时

134212

90000

187.5

2.28

130分钟后

2.2小时

138208

156000

325

6.18

221分钟后

3.7小时

147304

265200

552.5

15.07

271分钟后

4.5小时

145928

325200

677.5

13.72

310分钟后

5.2小时

147046

372000

775

14.81

370分钟后

6.2小时

165228

444000

925

32.57

376分钟后

6.3小时

172436

451200

940

39.61



测试15

使用dispose并将CG移除到数据更新函数外,将CG的时间设为22.5秒,测试结果:

动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

打开网页

-

131640

-

-

-

16分钟后

0.3小时

148724

19200

40

16.68

45分钟后

0.8小时

158464

54000

112.5

26.2

89分钟后

1.5小时

164880

106800

222.5

32.46

121分钟后

2小时

162964

145200

302.5

30.59

254分钟后

4.2小时

215684

304800

635

82.07

278分钟后

4.6小时

223944

333600

695

90.14


测试16

与测试9代码一样,将CG的时间改为22.5秒,测试结果:

动作

小时

内存(KB)

刷新次数

对应时间(天)

增加内存(MB)

打开网页

-

110804

-

-

-

9分钟后

0.2小时

119116

10800

22.5

8.12

21分钟后

0.4小时

123068

25200

52.5

11.98

53分钟后

0.9小时

135848

63600

132.5

24.46

94分钟后

1.6小时

162104

112800

235

50.1

125分钟后

2.1小时

169964

150000

312.5

57.77

260分钟后

4.3小时

201064

312000

650

88.14

283分钟后

4.7小时

197256

339600

707.5

84.43


测试20

基于测试11,将图表数量改为1,并将刷新时间改为5秒,更改部分如下:
            var i = 2;            for (; --i;) {                initCharts('main' + i);            }                setInterval(setData, 5000);

测试结果:

时间变化(小时)

刷新次数

总体内存(MB)

消耗内存(KB)

内存变化(KB)

0

0

160

48060

0

0.25

180

153

52352

4292

0.55

396

154

52644

4584

1.1

792

154

53276

5216

2.1

1512

155

52948

4888

4.45

3204

159

56552

8492

5.13

3696

167

56212

8152

6.07

4368

165

57576

9516

8.25

5940

167

56304

8244

8.5

6120

166

56560

8500

12.87

9264

167

56752

8692

24.05

17316

167

56716

8656

28.5

20520

168

56800

8740

29.48

21228

168

57860

9800

30.58

22020

167

57100

9040

32.02

23052

167

57120

9060

46.02

33132

168

57952

9892

49.8

35856

169

57976

9916

52.53

37824

170

58268

10208

53.93

38832

170

58352

10292

54.77

39432

170

58300

10240

55.88

40236

169

58256

10196

108.72

78276

172

59416

11356


由于该组测试与测试13的刷新数据对比相近,进行对比,以供参考。

测试13

测试20

运行时间

刷新次数

消耗内存/KB

运行时间

刷新次数

消耗内存/KB

10分钟

12000

9400.32

24.05小时

17316

8656

32分钟

38400

9185.28

54.77小时

38832

10240

56分钟

67200

12011.52

108.72小时

78276

11356


选取测试20数据稳定后的数据作散点图,如图2所示,预计线性函数为:

y =1609.9x – 7×107

图2 测试20稳定数据的散点图及趋势的线性预测


测试21

基于测试20,将CG时间改为5秒,并将CG移入到数据刷新部分,核心代码:
setData = function () {    option.series[0].data.splice(0, option.series[0].data.length);    $.ajax({        url: 'ajax/data.asp?t='+Math.random(),        success: function (result) {            result = $.parseJSON(result);            option.series[0].data = result.dataset;            myChart.clear().setOption(option);            result = null;            if (window.CollectGarbage) {                CollectGarbage();            }        }    });};
测试数据:

时间变化(小时)

刷新次数

总体内存(MB)

消耗内存(KB)

内存变化(KB)

0

0

158

46672

0

0.05

36

148

47816

1144

0.37

264

148

48280

1608

0.92

660

149

48636

1964

1.88

1356

151

48764

2092

4.38

3156

153

51952

5280

4.92

3540

160

51248

4576

5.88

4236

159

50529

3857

8.03

5784

161

51960

5288

8.33

6000

160

50304

3632

12.67

9120

161

51164

4492

23.85

17172

161

51748

5076

28.32

20388

163

53756

7084

29.28

21084

163

54244

7572

30.4

21888

163

54048

7376

31.82

22908

165

55556

8884

45.8

32976

163

53460

6788

49.6

35712

162

52536

5864

52.33

37680

163

53292

6620

53.73

38688

163

53672

7000

54.58

39300

162

52864

6192

55.7

40104

162

52868

6196

108.53

78144

165

53724

7052


与测试13对比:

测试13

测试21

运行时间

刷新次数

消耗内存/KB

运行时间

刷新次数

消耗内存/KB

10分钟

12000

9400.32

23.85小时

17172

5076

32分钟

38400

9185.28

53.73小时

38688

7000

56分钟

67200

12011.52

108.53

78144

7052


测试21数据作散点图,如图3所示,预计线性函数为:

y = 1401.1x 6×107


图3 测试21数据的散点图及趋势的线性预测

测试22

基于测试20,将CG时间改为5秒,测试结果:

时间变化(小时)

刷新次数

总体内存(MB)

消耗内存(KB)

内存变化(KB)

0

0

158

53180

0

0.05

36

158

53948

768

0.6

432

163

55896

2716

1.53

1104

163

55952

2772

4.07

2928

164

56056

2876

4.57

3288

164

56196

3016

5.57

4008

163

55584

2404

7.72

5556

165

57844

4664

12.37

8904

173

59272

6092

23.53

16944

182

65176

11996

28

20160

183

65800

12620

29

20880

183

65624

12444

30.07

21648

182

65568

12388

31.5

22680

183

65884

12704

45.43

32712

183

66852

13672

49.27

35472

185

68556

15376


与测试13对比:

测试13

测试21

运行时间

刷新次数

消耗内存/KB

运行时间

刷新次数

消耗内存/KB

10分钟

12000

9400.32

23.53小时

16944

11996

32分钟

38400

9185.28

49.27小时

35472

15376


选取测试22中数据作散点图,如图4所示,预计线性函数为:

y =7582.8x – 3×108


图4 测试22数据的散点图及趋势的线性预测

说明:以下测试以CPU的运行时间作为计时的标准,之前的测试标准不一致。

测试25

该组测试将CG时间设为10秒,测试结果如下:

时间变化(小时)

刷新次数

内存消耗(KB)

总内存消耗(MB)

内存变化(KB)

0

0

56800

167

0

40.78

29364

68256

188

11456

43.08

31020

68728

192

11928

44.08

31740

68036

193

11236

45.25

32580

69860

197

13060

47.12

33924

69128

199

12328

55.13

39696

69708

205

12908



选取测试25中数据作散点图,如图5所示,预计线性函数为:

y =3717.8x – 2×108


图5 测试25数据的散点图及趋势的线性预测

测试26

该测试组将CG时间设为15秒,测试结果如下:

时间变化(小时)

刷新次数

内存消耗(KB)

总内存消耗(MB)

内存变化(KB)

0

0

53756

163

0

41.85

30132

74516

222

20760

44.15

31788

74356

224

20600

45.13

32496

75644

226

21888

46.3

33336

74212

227

20456

48.17

34680

74172

231

20416

56.17

40440

74616

236

20860


选取测试26中数据作散点图,如图6所示,预计线性函数为:

y =6206.4x – 3×108


图6 测试26数据的散点图及趋势的线性预测

测试27

该组测试将CG时间设为20秒,测试结果如下:

时间变化(小时)

刷新次数

内存消耗(KB)

总内存消耗(MB)

内存变化(KB)

0

0

65800

183

0

41.78

30084

70340

205

4540

44.08

31740

71120

209

5320

45.08

32460

70132

210

4332

46.22

33276

70112

213

4312

48.12

34644

70652

216

4852

56.12

40404

70636

209

4836


选取测试27中数据作散点图,如图7所示,预计线性函数为:

y = 1371.4x – 6×107



图7 测试27数据的散点图及趋势的线性预测

三、测试结果

1、测试1~5、7~16的测试结果图





图8 Echarts内存测试结果散点图


图9各个测试结果的线性回归函数预测图





图10各个测试结果的线性回归函数预测图(放大400倍后)


根据图9和图10可以看出,各个结果的斜率由小到大,如表2所示:

表2 各个测试结果的预测线性回归函数斜率排序



由此可以得出结论,就是内存优化最好测试组是测试11,最差的测试效果是测试1。


2、测试20~22、25~26的测试结果

根据两组测试的散点图作出的线性函数预测的斜率排序,如表3所示:


表3 测试20~22、25~27组测试结果斜率排名

斜率(越小越好)

测试

1371.46

测试27

1401.1

测试21

1609.9

测试20

3717.8

测试25

6208

测试26

7582.8

测试22



由此可以得到结论,在测试组20~22、25~27中,测试结果最好的,是测试组27,最差效果是22。即每次跟新数据前使用ECharts自带的clear功能并每20秒CG一次。

附录 测试代码结构(以测试11为例)



图5 闭包函数执行结构

(function () {    //    //ChartsClass       自定义图表类    //@param id         建立图表的DOM容器id    //    function ChartsClass(id) {            //建立并初始化图表对象        var myChart = echarts.init(document.getElementById(id)),            //图表显示的数据            dataset = [],            option = {                series: [                    {                        //将数据绑定到参数中                        "data": dataset                    }                ]                //其他参数            },            //            //setData   设置/更新数据的方法            //            setData = function () {                //手动清理上次的数据                dataset.splice(0, dataset.length);                //随机产生新的数据                for (var i = 16; --i;) {                    dataset.push(Math.ceil(Math.random() * 200));                }                //使用清理内存clear和重新设置参数setOption                myChart.clear().setOption(option);            };        //执行设置数据的方法,并每50ms更新一次        setData();        setInterval(setData, 50);    }    //建立10个图表    var i = 11;    for (; --i;) {        ChartsClass('main' + i);    }    //定时清理内存,仅针对IE    if (window.CollectGarbage) {        setInterval(CollectGarbage, 300000);    }}());

测试26
        (function () {            function initCharts(id) {                // 基于准备好的dom,初始化echarts图表                var myChart = echarts.init(document.getElementById(id));                var dataset = [],                    option = {                        tooltip: {                            show: true                        },                        legend: {                            data: ['销量']                        },                        xAxis: [                            {                                type: 'category',                                data: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"]                            }                        ],                        yAxis: [                            {                                type: 'value'                            }                        ],                        series: [                            {                                "name": "销量",                                "type": "bar",                                "data": dataset                            }                        ],                        animation: false                    },                    setData = function () {                        option.series[0].data.splice(0, option.series[0].data.length);                        $.ajax({                            url: 'ajax/data.asp?t=' + Math.random(),                            success: function (result) {                                result = $.parseJSON(result);                                option.series[0].data = [].concat(result.dataset);                                myChart.clear().setOption(option);                                result = null;                            }                        });                    };                setData();                setInterval(setData, 5000);            }            var i = 2;            for (; --i;) {                initCharts('main' + i);            }            if (window.CollectGarbage) {                setInterval(CollectGarbage, 15000);            }        }());<strong></strong>


0 0
原创粉丝点击