从其它平台迁移而来


开发过程中经常会需要使用到延时功能,Delphi中有不少实现延时的方法,网上已有不少文章做过说明和分析,但本着实践出真知的态度,还是亲自动手研究一番心里比较踏实。

常用的延时方法

Sleep

Sleep(n),延时n毫秒,延时过程中程序不响应,一般延时较小时使用。

在主线程中使用,延时较大(100+)的话会起程序假死,一般在子线程中使用较多。

无论在主线程还是子线程中,延时较长的话(如 2000 ms),一般不一次性Sleep(2000),而是分多次循环Sleep。有时为了能在延时过程中响应外部消息,还会加上Application.ProcessMessages;,如:

1
2
3
4
5
6
//延时 2000 ms
for i := 0 to 19 do
begin
  Sleep(100);
  Application.ProcessMessages;
end;

Timer

Timer为定时器,用于周期性地执行某个处理。也可用来实现延时,延时过程中不会引起程序假死,

GetTickCount

GetTickCount返回从操作系统启动到当前所经过的毫秒数,一般用于计算代码段的用时。配合循环使用也可达到延时的功能。

1
2
3
4
n := GetTickCount;
repeat
  Application.ProcessMessages; //若延时过程中需要响应消息可加上此句
until  GetTickCount >= n + ms; //ms为延时的毫秒数

注意:使用以上代码进行延时的过程中,CPU使用率会异常地高(事实上,不加限制一直跑的循环都会导致CPU使用率过高)。

小结

以上是对SleepTimerGetTickCount用于延时的简单说明,个人经验:通常较小延时的场景用Sleep,较大延时的场景用Timer,评估代码段耗时的场景用GetTickCount。至于为什么这样用,以前是不清楚的,但通过对三者的精度分析,目前已知晓来龙去脉。

延时精度分析

上文已经提到,一般用GetTickCount来分析代码段耗时,但由于本次GetTickCount在被测行列,故另寻他法。

  1. 本次测试假定系统时间是足够精确的,因此使用Now分别在延时前后获取系统当前时间来进行耗时评估。

  2. 为使测试更具代表性,每个测试点测试100次,取算术平均值。

  3. 1ms~100ms内,测试点步长为1ms,在100ms~1000ms内,测试点步长为10ms

  4. 为尽可能减小干扰,测试过程中未使用Application.ProcessMessages;,也未使用并行。

测试结果

XE10编译,Win10下运行,经过近5个小时的测试,结果终于出炉了。

延时(ms) Sleep GetTickCount Timer
1 1.70 15.58 15.64
2 2.71 15.63 15.50
3 3.67 15.62 15.63
4 4.56 15.63 15.44
5 5.54 15.62 15.56
6 6.52 15.63 15.51
7 7.53 15.63 15.55
8 8.54 15.61 15.49
9 9.52 15.63 15.50
10 10.55 15.63 15.48
11 11.57 15.62 15.53
12 12.73 15.63 15.56
13 13.64 15.63 15.52
14 14.53 15.61 15.53
15 15.52 15.63 15.54
16 16.59 24.85 24.79
17 17.53 31.24 31.16
18 18.54 31.26 31.22
19 19.51 31.24 31.20
20 20.58 31.25 31.18
21 21.51 31.26 31.21
22 22.51 31.24 31.18
23 23.55 31.26 31.17
24 24.53 31.25 31.24
25 25.55 31.24 31.26
26 26.52 31.26 31.24
27 27.50 31.25 31.18
28 28.56 31.24 31.19
29 29.50 31.26 31.27
30 30.54 31.24 31.09
31 31.51 31.25 31.24
32 32.53 41.72 41.64
33 33.55 46.87 46.76
34 34.58 46.89 46.75
35 35.50 46.87 46.79
36 36.55 46.88 46.76
37 37.52 46.87 46.72
38 38.53 46.88 46.77
39 39.54 46.87 46.75
40 40.52 46.88 46.77
41 41.54 46.87 46.80
42 42.53 46.88 46.72
43 43.53 46.87 46.76
44 44.50 46.88 46.80
45 45.59 46.87 46.69
46 46.54 46.87 46.84
47 47.51 50.00 49.82
48 48.55 62.50 62.48
49 49.54 62.51 62.44
50 50.61 62.50 62.42
51 51.56 62.49 62.45
52 52.57 62.50 62.48
53 53.51 62.51 62.47
54 54.55 62.49 62.35
55 55.54 62.50 62.50
56 56.53 62.51 62.47
57 57.53 62.50 62.40
58 58.58 62.49 62.43
59 59.51 62.50 62.46
60 60.55 62.51 62.44
61 61.54 62.49 62.47
62 62.53 62.50 62.48
63 63.54 75.00 74.87
64 64.54 78.13 77.93
65 65.57 78.12 78.02
66 66.53 78.13 78.07
67 67.54 78.13 78.06
68 68.57 78.12 78.04
69 69.55 78.13 77.97
70 70.55 78.12 78.01
71 71.56 78.12 78.07
72 72.56 78.13 78.04
73 73.53 78.12 78.00
74 74.53 78.13 78.04
75 75.57 78.12 78.08
76 76.52 78.12 77.95
77 77.47 78.14 78.00
78 78.56 78.12 78.06
79 79.52 93.75 93.60
80 80.55 93.75 93.74
81 81.55 93.74 93.64
82 82.60 93.76 93.74
83 83.68 93.75 93.66
84 84.50 93.75 93.74
85 85.59 93.75 93.62
86 86.54 93.75 93.73
87 87.54 93.75 93.71
88 88.58 93.75 93.66
89 89.55 93.75 93.76
90 90.60 93.75 93.66
91 91.53 93.75 93.60
92 92.53 93.75 93.83
93 93.49 93.75 93.70
94 94.53 100.00 99.93
95 95.58 109.38 109.35
96 96.50 109.37 109.37
97 97.56 109.37 109.39
98 98.52 109.38 109.31
99 99.56 109.38 109.35
100 100.56 109.37 109.25
110 110.59 124.89 124.96
120 120.62 125.00 125.04
130 130.51 140.62 140.50
140 140.58 140.62 140.63
150 150.60 156.26 156.22
160 160.55 171.88 171.77
170 170.52 171.87 171.85
180 180.49 187.49 187.47
190 190.56 203.13 202.94
200 200.57 203.13 203.05
210 210.57 218.74 218.64
220 220.58 234.39 234.31
230 230.56 234.37 234.31
240 240.58 250.00 249.87
250 250.57 249.99 250.04
260 260.54 265.63 265.38
270 270.54 281.25 281.26
280 280.59 281.26 281.27
290 290.53 296.86 296.76
300 300.57 312.51 312.43
310 310.58 312.50 312.43
320 320.57 328.12 328.10
330 330.62 343.75 343.68
340 340.56 343.75 343.75
350 350.57 359.37 359.29
360 360.55 375.01 374.91
370 370.56 375.00 374.94
380 380.49 390.62 390.57
390 390.57 390.63 390.46
400 400.51 406.25 406.30
410 410.52 421.87 421.70
420 420.57 421.87 421.88
430 430.57 437.50 437.42
440 440.57 453.13 452.96
450 450.57 453.13 453.09
460 460.59 468.74 468.65
470 470.55 484.38 484.26
480 480.59 484.37 484.36
490 490.61 500.00 499.90
500 500.55 500.01 499.97
510 510.56 515.62 515.49
520 520.59 531.25 531.19
530 530.57 531.25 531.27
540 540.68 546.87 546.77
550 550.54 562.51 562.45
560 560.61 562.49 562.55
570 570.54 578.13 577.90
580 580.54 593.75 593.75
590 590.56 593.75 593.75
600 600.56 609.38 609.23
610 610.63 625.00 624.92
620 620.57 624.99 624.99
630 630.64 640.63 640.45
640 640.52 640.63 640.52
650 650.48 656.24 656.05
660 660.59 671.88 671.78
670 670.58 671.88 671.83
680 680.53 687.50 687.45
690 690.60 703.12 703.00
700 700.60 703.13 703.07
710 710.59 718.74 718.66
720 720.70 734.38 734.27
730 730.64 734.37 734.32
740 740.52 750.01 749.96
750 750.65 749.99 749.93
760 760.54 765.63 765.71
770 770.62 781.25 781.35
780 780.54 781.25 781.18
790 790.55 796.87 797.00
800 800.53 812.51 812.40
810 810.57 812.49 812.50
820 820.58 828.13 828.14
830 830.62 843.75 843.69
840 840.57 843.76 843.78
850 850.56 859.37 859.24
860 860.60 875.00 874.96
870 870.66 874.99 875.07
880 880.60 890.63 890.50
890 890.50 890.62 890.62
900 900.57 906.25 906.20
910 910.63 921.87 921.68
920 920.56 921.87 921.81
930 930.56 937.51 937.47
940 940.56 953.12 952.99
950 950.58 953.13 952.95
960 960.60 968.75 968.66
970 970.51 984.37 984.24
980 980.55 984.38 984.33
990 990.62 999.99 999.88
1000 1000.52 1000.01 999.83

为方便直观查看,绘成图,分别为常数坐标轴对数坐标轴

常数坐标轴

对数坐标轴

结果分析

从结果中可以看到:

  1. Sleep的稳定性最好,偏差均在1ms左右。

  2. GetTickcountTimer的结果高度重合,且呈阶梯状分布,阶梯差约15ms

经查MSDNGetTickcount的分辨率受系统Timer的限制,通常在10ms~16ms范围内,测试结果与此吻合。

总结

需要高精度延时的场景用Sleep,长延时用Sleep + 循环;一般精度的场景用GetTickcount + 循环;需要定时周期性处理的场景用Timer

GetTickcount + 循环容易造成CPU占用率偏高,可以用GetTickcount + 循环 + Sleep(1)来降低CPU占用率:

1
2
3
4
n := GetTickCount;
repeat
  Sleep(1);
until  GetTickCount >= n + ms;

题外话

后来从别人的文章中发现了一种高精度的计时方法,用于评估代码段的执行时间:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var
  Frequency, bCount, eCount: Int64;
  UsedTime: Double;
begin
  QueryPerformanceFrequency(Frequency);
  QueryPerformanceCounter(bCount);
  //被评估代码段
  QueryPerformanceCounter(eCount);
  UsedTime := (eCount - bCount) / Frequency * 1000; //单位:ms
end;

使用这种计时方法重新运行后的结果如下:

延时 Sleep GetTickCount Timer
1 1.94 15.48 15.60
2 2.85 15.63 15.57
3 3.84 15.63 15.57
4 4.82 15.62 15.57
5 5.90 15.63 15.54
6 6.76 15.63 15.56
7 7.81 15.62 15.55
8 8.77 15.63 15.60
9 9.79 15.63 15.55
10 10.73 15.62 15.56
11 11.76 15.63 15.58
12 12.79 15.63 15.59
13 13.76 15.62 15.54
14 14.76 15.63 15.61
15 15.76 15.63 15.57
16 16.75 24.99 24.93
17 17.78 31.26 31.13
18 18.71 31.25 31.18
19 19.72 31.26 31.18
20 20.73 31.25 31.17
21 21.67 31.25 31.19
22 22.70 31.26 31.18
23 23.82 31.25 31.20
24 24.66 31.25 31.14
25 25.62 31.26 31.22
26 26.72 31.25 31.14
27 27.70 31.25 31.19
28 28.62 31.26 31.14
29 29.73 31.25 31.19
30 30.57 31.26 31.18
31 31.63 31.25 31.12
32 32.57 41.72 41.65
33 33.60 46.87 46.83
34 34.60 46.87 46.80
35 35.61 46.87 46.81
36 36.55 46.87 46.80
37 37.62 46.87 46.78
38 38.59 46.87 46.81
39 39.58 46.87 46.82
40 40.60 46.87 46.79
41 41.58 46.87 46.75
42 42.61 46.87 46.83
43 43.59 46.87 46.82
44 44.63 46.87 46.76
45 45.58 46.87 46.79
46 46.56 46.87 46.74
47 47.60 50.01 49.81
48 48.51 62.50 62.34
49 49.60 62.49 62.42
50 50.56 62.50 62.37
51 51.57 62.50 62.46
52 52.59 62.49 62.36
53 53.51 62.50 62.42
54 54.58 62.50 62.37
55 55.60 62.50 62.38
56 56.56 62.49 62.42
57 57.56 62.50 62.38
58 58.57 62.50 62.43
59 59.61 62.49 62.39
60 60.59 62.51 62.34
61 61.54 62.50 62.44
62 62.57 62.50 62.43
63 63.61 74.99 74.89
64 64.55 78.12 78.06
65 65.56 78.13 78.07
66 66.52 78.12 78.04
67 67.57 78.12 78.08
68 68.53 78.13 78.05
69 69.59 78.12 78.02
70 70.57 78.12 78.06
71 71.58 78.13 78.04
72 72.56 78.12 78.06
73 73.62 78.13 78.05
74 74.59 78.12 78.06
75 75.58 78.13 78.05
76 76.61 78.12 78.01
77 77.63 78.12 78.10
78 78.60 78.13 78.01
79 79.58 93.75 93.64
80 80.59 93.75 93.68
81 81.58 93.75 93.67
82 82.62 93.75 93.69
83 83.58 93.75 93.61
84 84.55 93.75 93.65
85 85.60 93.75 93.67
86 86.57 93.75 93.67
87 87.60 93.75 93.69
88 88.62 93.75 93.62
89 89.59 93.76 93.70
90 90.60 93.75 93.66
91 91.65 93.75 93.66
92 92.58 93.75 93.63
93 93.62 93.75 93.70
94 94.61 100.00 99.78
95 95.59 109.37 109.24
96 96.61 109.38 109.31
97 97.62 109.38 109.29
98 98.65 109.38 109.32
99 99.61 109.37 109.29
100 100.59 109.38 109.34
110 110.57 125.01 124.91
120 120.56 125.00 125.03
130 130.52 140.62 140.52
140 140.51 140.62 140.57
150 150.60 156.25 156.21
160 160.58 171.88 171.77
170 170.60 171.87 171.86
180 180.59 187.50 187.43
190 190.60 203.13 202.99
200 200.61 203.13 203.13
210 210.59 218.74 218.64
220 220.62 234.38 234.28
230 230.60 234.37 234.31
240 240.59 250.00 249.97
250 250.58 249.99 250.00
260 260.75 265.63 265.59
270 270.56 281.25 281.14
280 280.61 281.25 281.26
290 290.62 296.88 296.75
300 300.62 312.49 312.45
310 310.57 312.50 312.52
320 320.55 328.12 328.01
330 330.59 343.75 343.67
340 340.54 343.75 343.72
350 350.57 359.38 359.30
360 360.57 374.99 374.96
370 370.60 375.00 374.93
380 380.61 390.62 390.57
390 390.53 390.62 390.55
400 400.62 406.25 406.20
410 410.58 421.87 421.81
420 420.58 421.88 421.89
430 430.56 437.50 437.38
440 440.56 453.12 453.06
450 450.68 453.13 453.03
460 460.65 468.76 468.73
470 470.71 484.37 484.27
480 480.72 484.37 484.39
490 490.69 499.99 499.87
500 500.66 500.00 499.95
510 510.63 515.63 515.61
520 520.61 531.25 531.17
530 530.58 531.25 531.29
540 540.55 546.88 546.80
550 550.53 562.50 562.39
560 560.50 562.50 562.42
570 570.47 578.12 578.09
580 580.45 593.75 593.69
590 590.42 593.75 593.79
600 600.39 609.37 609.23
610 610.57 625.00 624.93
620 620.59 625.00 624.96
630 630.55 640.63 640.54
640 640.61 640.63 640.56
650 650.60 656.25 656.27
660 660.60 671.87 671.77
670 670.63 671.87 671.88
680 680.56 687.50 687.43
690 690.61 703.13 703.00
700 700.61 703.12 703.11
710 710.56 718.75 718.67
720 720.55 734.38 734.27
730 730.60 734.37 734.31
740 740.56 750.00 750.01
750 750.56 750.00 749.91
760 760.58 765.62 765.51
770 770.59 781.25 781.22
780 780.56 781.25 781.24
790 790.58 796.87 796.82
800 800.56 812.51 812.37
810 810.60 812.50 812.54
820 820.59 828.12 827.99
830 830.60 843.75 843.67
840 840.58 843.75 843.77
850 850.57 859.37 859.28
860 860.58 875.00 874.89
870 870.54 875.00 874.97
880 880.58 890.63 890.57
890 890.55 890.63 890.57
900 900.53 906.24 906.16
910 910.61 921.87 921.76
920 920.63 921.87 921.84
930 930.56 937.50 937.43
940 940.57 953.12 953.06
950 950.59 953.13 953.05
960 960.55 968.75 968.63
970 970.44 984.38 984.30
980 980.38 984.38 984.28
990 990.36 999.99 999.99
1000 1000.32 1000.00 999.98