测试背景是一款自动化软件平台上的逻辑模块性能对比。能够实现复杂逻辑的目前有结构化文本(指令表)和Python(Jython)两个。
三菱指令的解释器是原创的,因为没有相关的Java支持。Python程序的解释器是Jython2.7.2。
由于功能等级不同,三菱指令的编译时间较快,对程序的修改是无缝接入的。Jython的compile函数调用时间约5秒,但可以使用Python的高级功能。实际运行时不再编译,所以这个时间没有测。
编译完成后运行几分钟后,对逻辑区的运行时间进行测量,排除内部IO区的干扰(例程无物理IO)后,对程序进行修改,使运行时间接近。所需时间最小值为0.013ms时,两者的程序片段如下:
Python:
D[11] = random.randrange(10)
D[12] = 2
D[13] = 3
三菱Q系列指令:
0 LDI T1023
1 OUT T1023 K1
5 INV
6 OUT M61439
7 LDP M61439
8 OUT M61436
9 INC D20475
11 LD SM400
12 / D20475 K10 D20469
15 MOV D20470 D20475
17 LD M61439
18 AND= D20475 K0
21 INV
22 CJ P4096
24 LD SM400
25 + K1 D20477
28 / D20477 K16 D20467
31 MOV D20468 D20477
33 P4096
34 LD<= D20477 K8
37 CJ P4097
39 LD SM400
40 - K16 D20477 D20476
43 JMP P4098
45 P4097
46 LD SM400
47 MOV D20477 D20476
49 P4098
50 LD<> D20476 K0
53 CJ P4099
55 LD SM400
56 MOV K1 D0
58 MOV K1 D1
60 MOV K0 D2
62 JMP P4100
64 P4099
65 LD<> D20476 K1
68 CJ P4101
70 LD SM400
71 MOV K1 D0
73 / D0 K2 D20465
76 MOV D20465 D0
78 MOV K1 D1
80 MOV K0 D2
82 JMP P4100
84 P4101
85 LD<> D20476 K2
88 CJ P4102
90 LD SM400
91 MOV K0 D0
93 MOV K1 D1
95 MOV K0 D2
97 JMP P4100
99 P4102
100 LD<> D20476 K3
103 CJ P4103
105 LD SM400
106 MOV K0 D0
108 MOV K1 D1
110 / D1 K2 D20465
113 MOV D20465 D1
115 MOV K0 D2
117 JMP P4100
119 P4103
120 LD<> D20476 K4
123 CJ P4104
125 LD SM400
126 MOV K0 D0
128 MOV K0 D1
130 MOV K0 D2
132 JMP P4100
134 P4104
135 LD<> D20476 K5
138 CJ P4105
140 LD SM400
141 MOV K0 D0
143 MOV K-1 D1
145 / D1 K2 D20465
148 MOV D20465 D1
150 MOV K1 D2
152 / D2 K2 D20465
155 MOV D20465 D2
157 JMP P4100
159 P4105
160 LD<> D20476 K6
163 CJ P4106
165 LD SM400
166 MOV K0 D0
168 MOV K-1 D1
170 MOV K1 D2
172 JMP P4100
174 P4106
175 LD<> D20476 K7
178 CJ P4107
180 LD SM400
181 MOV K1 D0
183 / D0 K2 D20465
186 MOV D20465 D0
188 MOV K-1 D1
190 MOV K1 D2
192 JMP P4100
194 P4107
195 LD<> D20476 K8
198 CJ P4108
200 LD SM400
201 MOV K1 D0
203 MOV K-1 D1
205 MOV K1 D2
207 JMP P4100
209 P4108
210 LD SM400
211 MOV K1 D0
213 MOV K1 D1
215 MOV K1 D2
217 P4100
218 LD= D0 K1
221 AND= D1 K1
224 AND= D2 K0
227 CJ P4109
229 LD= D0 K0
232 AND= D1 K1
235 AND= D2 K0
238 CJ P4111
240 LD= D0 K0
243 AND= D1 K0
246 AND= D2 K0
249 CJ P4112
251 LD= D0 K0
254 AND= D1 K-1
257 AND= D2 K1
260 CJ P4113
262 LD= D0 K1
265 AND= D1 K-1
268 AND= D2 K1
271 CJ P4114
273 LD SM400
274 MOV K-1 D3
276 JMP P4110
278 P4114
279 LD SM400
280 MOV K1 D3
282 JMP P4110
284 P4113
285 LD SM400
286 MOV K2 D3
288 JMP P4110
290 P4112
291 LD SM400
292 MOV K3 D3
294 JMP P4110
296 P4111
297 LD SM400
298 MOV K4 D3
300 JMP P4110
302 P4109
303 LD SM400
304 MOV K5 D3
306 P4110
307 LD M61439
308 INC D20474
310 LD SM400
311 / D20474 K10 D20469
314 MOV D20470 D20474
316 LD= D20474 K0
319 OUT M61438
320 LDP M61438
321 OUT M61437
322 LD M61437
323 RND D11
325 LD M61437
326 RND D12
328 LD M61437
329 RND D13
331 LD M61437
332 RND D21
334 LD M61437
335 RND D22
337 LD M61437
338 RND D23
340 LDI M61437
341 CJ P4115
343 LD SM400
344 MOV K100 D20473
346 * D20473 K100 D20467
349 MOV D20467 D20473
351 MOV K1000 D20472
353 MOV K10 D20471
355 / D11 D20473 D20467
358 / D20468 D20472 D20465
361 MOV D20465 D11
363 / D12 D20473 D20465
366 / D20466 D20472 D20463
369 MOV D20463 D12
371 / D13 D20473 D20463
374 / D20464 D20472 D20461
377 MOV D20461 D13
379 / D21 D20473 D20461
382 / D20462 D20471 D20459
385 MOV D20459 D21
387 / D22 D20473 D20459
390 / D20460 D20471 D20457
393 MOV D20457 D22
395 / D23 D20473 D20457
398 / D20458 D20471 D20455
401 MOV D20455 D23
403 P4115
这段汇编对应的源程序如下:
(* 平台程序 *)
globalTicker_1();
梯形图主程序_1();
(* 业务程序 *)
一次方案流水灯_1(MAIN_SWITCH:= D0 ,
DISCONNECTOR_SWITCH:= D1 ,
EARTH_SWITCH:= D2 ,
STATE_DESCRIPTION:= D3 );
一次方案随机数_1(I_A:= D11 ,
I_B:= D12 ,
I_C:= D13 ,
U_A:= D21 ,
U_B:= D22 ,
U_C:= D23 );
=================================================
(*流水灯*)
INC(LDP(1,G_SYSTEMTICK) , TICK_COUNTER);
TICK_COUNTER := TICK_COUNTER MOD 10;
IF G_SYSTEMTICK AND (TICK_COUNTER = 0) THEN
ENGINE := ENGINE + 1;
ENGINE := ENGINE MOD 16;
END_IF;
IF ENGINE <= 8 THEN
STATE := ENGINE;
ELSE
STATE := 16 - ENGINE;
END_IF;
CASE STATE OF
0:
MAIN_SWITCH := 1;
DISCONNECTOR_SWITCH := 1;
EARTH_SWITCH := 0;
1:
MAIN_SWITCH := 1;MAIN_SWITCH := MAIN_SWITCH / 2;
DISCONNECTOR_SWITCH := 1;
EARTH_SWITCH := 0;
2:
MAIN_SWITCH := 0;
DISCONNECTOR_SWITCH := 1;
EARTH_SWITCH := 0;
3:
MAIN_SWITCH := 0;
DISCONNECTOR_SWITCH := 1;DISCONNECTOR_SWITCH := DISCONNECTOR_SWITCH / 2;
EARTH_SWITCH := 0;
4:
MAIN_SWITCH := 0;
DISCONNECTOR_SWITCH := 0;
EARTH_SWITCH := 0;
5:
MAIN_SWITCH := 0;
DISCONNECTOR_SWITCH := -1;DISCONNECTOR_SWITCH := DISCONNECTOR_SWITCH / 2;
EARTH_SWITCH := 1;EARTH_SWITCH := EARTH_SWITCH / 2;
6:
MAIN_SWITCH := 0;
DISCONNECTOR_SWITCH := -1;
EARTH_SWITCH := 1;
7:
MAIN_SWITCH := 1;MAIN_SWITCH := MAIN_SWITCH / 2;
DISCONNECTOR_SWITCH := -1;
EARTH_SWITCH := 1;
8:
MAIN_SWITCH := 1;
DISCONNECTOR_SWITCH := -1;
EARTH_SWITCH := 1;
ELSE
MAIN_SWITCH := 1;
DISCONNECTOR_SWITCH := 1;
EARTH_SWITCH := 1;
END_CASE;
IF MAIN_SWITCH = 1
AND DISCONNECTOR_SWITCH = 1
AND EARTH_SWITCH = 0 THEN
STATE_DESCRIPTION := 5;
ELSIF MAIN_SWITCH = 0
AND DISCONNECTOR_SWITCH = 1
AND EARTH_SWITCH = 0 THEN
STATE_DESCRIPTION := 4;
ELSIF MAIN_SWITCH = 0
AND DISCONNECTOR_SWITCH = 0
AND EARTH_SWITCH = 0 THEN
STATE_DESCRIPTION := 3;
ELSIF MAIN_SWITCH = 0
AND DISCONNECTOR_SWITCH = -1
AND EARTH_SWITCH = 1 THEN
STATE_DESCRIPTION := 2;
ELSIF MAIN_SWITCH = 1
AND DISCONNECTOR_SWITCH = -1
AND EARTH_SWITCH = 1 THEN
STATE_DESCRIPTION := 1;
ELSE
STATE_DESCRIPTION := -1;
END_IF;
===============================================
(*随机数:*)
INC(G_SYSTEMTICK,TICKER_COUNTER);
TICKER_COUNTER := TICKER_COUNTER MOD 10;
TIMER_SIGNAL := TICKER_COUNTER = 0;
TIMER_SIGNAL_P := LDP(TRUE,TIMER_SIGNAL) ;
RND( TIMER_SIGNAL_P , I_A );
RND( TIMER_SIGNAL_P , I_B );
RND( TIMER_SIGNAL_P , I_C );
RND( TIMER_SIGNAL_P , U_A );
RND( TIMER_SIGNAL_P , U_B );
RND( TIMER_SIGNAL_P , U_C );
IF TIMER_SIGNAL_P THEN
RAND_LIMIT := 1000;
RAND_LIMIT := RAND_LIMIT * 100;
I_DECS := 1000;
U_DECS := 10;
I_A := I_A MOD RAND_LIMIT / I_DECS;
I_B := I_B MOD RAND_LIMIT / I_DECS;
I_C := I_C MOD RAND_LIMIT / I_DECS;
U_A := U_A MOD RAND_LIMIT / U_DECS;
U_B := U_B MOD RAND_LIMIT / U_DECS;
U_C := U_C MOD RAND_LIMIT / U_DECS;
END_IF;
可以看到同样的时间三菱Q系列解释器可以比Python做更多的事情,就随机数的使用上,这些时间内Python只能做一次随机数,Q系列解释器可以调用6次随机数还能加一大堆别的事情。
测试只测展示出的这一段,Python对程序大小也比较敏感,把那个随机数的函数拿掉就会快一些。Python的程序规模大一点耗时就超过了1ms,而同样的事情Q系列指令解释器只需要0.02~0.08ms。结构化文本和梯形图的学习难度也小于Python,最终推荐用于自动化逻辑脚本编程的是结构化文本和梯形图,Python作为一种附加接口模块,用于通讯、文件处理等功能的二次开发。
续:
后来我又测试了不用库函数的程序,发现如果不用库函数的话,Python是可以和Java一比的,Python的性能主要是消耗在库函数上。