Sleep延迟不准确的问题(100分)

  • 主题发起人 DarwinZhang
  • 开始时间
D

DarwinZhang

Unregistered / Unconfirmed
GUEST, unregistred user!
我使用 Sleep(Time) 的时候发现,0&lt;Time&lt;=10时它就延迟10ms,<br>而在 10&lt;Timer&lt;=20时它就延迟 20ms......<br>进行跟踪,发现Sleep是调用kener32 的 sleepEx而 sleepEx是调用ntdll的 <br>NtDelayExecution 但 NtDelayExecution居然调用int 2e! 于是到这里就中断了。 [:(]<br>根据一位网友介绍,他这里的延迟是基本正常的,<br>那么究竟是什么原因造成这个差异的呢?<br><br>测试硬件:<br>K62-450+Win2k<br>测试时间长度的代码如下:<br>var<br>&nbsp;i:Integer;<br>&nbsp;bt,et:DWord;<br>begin<br>&nbsp;bt:=GetTickCount;<br>&nbsp;for i:=0 to 10000 do Sleep(1);<br>&nbsp;et:=GetTickCount;<br>&nbsp;ShowMessage(IntToStr(et-bt));<br>end;<br>
 
sleep不可能给你那么精确的,
 
10ms是操作系统最小的精度值了
 
可以看一下《DELPHI深度历险》
 
这位网友得测试结果:<br>procedure TForm1.Button4Click(Sender: TObject);<br>var<br>&nbsp; i:Integer;<br>&nbsp; OldTickCount:DWord;<br>&nbsp; BeginTime,EndTime:Int64;<br>begin<br>&nbsp; OldTickCount:=GetTickCount;<br>&nbsp; for i:=1 to 100 do<br>&nbsp; begin<br>&nbsp; &nbsp; //QueryPerformanceCounter(BeginTime); //QueryPerformanceCounter的耗时可以忽略<br>&nbsp; &nbsp; Sleep(1);<br>&nbsp; &nbsp; //QueryPerformanceCounter(EndTime);<br>&nbsp; end;<br>&nbsp; Caption:=IntToStr(GetTickCount-OldTickCount);<br>end;<br>&nbsp; 我发现GetTickCount只能精确到15ms左右,上面的代码我的运行结果在200ms左右。若将<br>Sleep(1) 改成 Sleep(10),结果则在1063-1078之间。
 
请 creation-zy 帮你看一下吧,记得他研究过这个。<br>
 
to beta兄: 我说的这位网友就是creation-zy兄! &nbsp;[:D]
 
还有,我注意到,在较低配置的机器上Sleep的精确程度就差一点,<br>不过只有三台不同配置的机器作为比较,到底是不是这样还很难讲。<br>即使是这样,难到Windows还会评估机器配置的好坏?[?]<br>
 
由于WINDOWS是抢占式的多任务的操作系统,操作系统是分片进行的,<br>我认为那些API函数和一些线程一样,同步状态占用系统资源,如果<br>系统培植低了,当然多占用CPU时间,因此得到的结果的精确度也要<br>差一些...个人的看法,不知道对不对?sleep本来就不是太精确,<br>尤其是在线程里,原因是WINDOWS不是实时的操作系统,误差在所<br>难免。<br>&lt;这个问题《DELPHI深度历险》上有详细的说明,作者用了一些其他<br>函数可以得到比较精确的时间,但是有一些限制&gt;
 
journer已经说了,看一下《Delphi深度历险》,里面有详细的说明
 
Sleep会导致线程调度,<br>转让CPU使用权,<br>而线程的切换本身就需要一定的时间,<br>而且也不可能会马上切换过来,因为别的线程也需要执行<br>如果需要的精度较高,可以使用多媒体定时器,<br>如果对精度要求不高,也可以进行误差修正<br>
 
我的意思是,为什么它很“精确”的固定在10ms档上面,而不是说它准不准的问题。<br>实际上,我们可以作到非常精确的定时大约0.1ms左右。(不是用sleep)<br>主要是想知道是什么原因造成的差异?
 
好像是NT没个任务最小的时间片是1/120m, 大约是8.3ms, 因为Sleep要切换任务, <br>所以估计是这个原因
 
下面是我的测试结果,侧使用的代码如下:<br>var<br>&nbsp; t1, t2, t3: Int64;<br>&nbsp; tc: Int64;<br>&nbsp; t: Cardinal;<br>begin<br>&nbsp; t := StrToIntDef(Edit1.Text, 0);<br>&nbsp; QueryPerformanceCounter(t1);<br>&nbsp; QueryPerformanceCounter(t2);<br>&nbsp; Sleep(t);<br>&nbsp; QueryPerformanceCounter(t3);<br>&nbsp; QueryPerformanceFrequency(tc);<br>&nbsp; Memo1.Lines.Add(Format('Sleep: %dms, 实际时间: %.6fs',<br>&nbsp; &nbsp; [t, ((t3 - t2) - (t2 - t1))/tc]));<br><br><br>测试结果,多次测试:<br>Sleep: 0ms, 实际时间: 0.000005s<br>Sleep: 0ms, 实际时间: 0.000025s<br>Sleep: 0ms, 实际时间: 0.000007s<br>Sleep: 0ms, 实际时间: 0.000023s<br>Sleep: 0ms, 实际时间: 0.000007s<br>Sleep: 0ms, 实际时间: 0.000006s<br>Sleep: 0ms, 实际时间: 0.000006s<br>Sleep: 0ms, 实际时间: 0.000651s<br>Sleep: 0ms, 实际时间: 0.000023s<br>Sleep: 0ms, 实际时间: 0.000348s<br><br>Sleep: 1ms, 实际时间: 0.000039s<br>Sleep: 1ms, 实际时间: 0.000371s<br>Sleep: 1ms, 实际时间: 0.000057s<br>Sleep: 1ms, 实际时间: 0.000053s<br>Sleep: 1ms, 实际时间: 0.000541s<br>Sleep: 1ms, 实际时间: 0.000028s<br>Sleep: 1ms, 实际时间: 0.000124s<br>Sleep: 1ms, 实际时间: 0.000693s<br>Sleep: 1ms, 实际时间: 0.000778s<br>Sleep: 1ms, 实际时间: 0.000734s<br><br>Sleep: 2ms, 实际时间: 0.001126s<br>Sleep: 2ms, 实际时间: 0.001369s<br>Sleep: 2ms, 实际时间: 0.001187s<br>Sleep: 2ms, 实际时间: 0.001354s<br>Sleep: 2ms, 实际时间: 0.001340s<br>Sleep: 2ms, 实际时间: 0.001219s<br>Sleep: 2ms, 实际时间: 0.001152s<br>Sleep: 2ms, 实际时间: 0.001282s<br>Sleep: 2ms, 实际时间: 0.001395s<br>Sleep: 2ms, 实际时间: 0.001408s<br><br>Sleep: 3ms, 实际时间: 0.002905s<br>Sleep: 3ms, 实际时间: 0.002316s<br>Sleep: 3ms, 实际时间: 0.002096s<br>Sleep: 3ms, 实际时间: 0.003004s<br>Sleep: 3ms, 实际时间: 0.002216s<br>Sleep: 3ms, 实际时间: 0.002216s<br>Sleep: 3ms, 实际时间: 0.002109s<br>Sleep: 3ms, 实际时间: 0.002721s<br>Sleep: 3ms, 实际时间: 0.002695s<br>Sleep: 3ms, 实际时间: 0.002254s<br><br>Sleep: 4ms, 实际时间: 0.003393s<br>Sleep: 4ms, 实际时间: 0.003093s<br>Sleep: 4ms, 实际时间: 0.003585s<br>Sleep: 4ms, 实际时间: 0.003366s<br>Sleep: 4ms, 实际时间: 0.003348s<br>Sleep: 4ms, 实际时间: 0.003887s<br>Sleep: 4ms, 实际时间: 0.003288s<br>Sleep: 4ms, 实际时间: 0.003528s<br>Sleep: 4ms, 实际时间: 0.003077s<br>Sleep: 4ms, 实际时间: 0.003968s<br><br>Sleep: 5ms, 实际时间: 0.004355s<br>Sleep: 5ms, 实际时间: 0.004257s<br>Sleep: 5ms, 实际时间: 0.004781s<br>Sleep: 5ms, 实际时间: 0.004953s<br>Sleep: 5ms, 实际时间: 0.004356s<br>Sleep: 5ms, 实际时间: 0.004418s<br>Sleep: 5ms, 实际时间: 0.004482s<br>Sleep: 5ms, 实际时间: 0.004586s<br>Sleep: 5ms, 实际时间: 0.004953s<br>Sleep: 5ms, 实际时间: 0.004522s<br><br>Sleep: 10ms, 实际时间: 0.009490s<br>Sleep: 10ms, 实际时间: 0.010026s<br>Sleep: 10ms, 实际时间: 0.009135s<br>Sleep: 10ms, 实际时间: 0.009193s<br>Sleep: 10ms, 实际时间: 0.009542s<br>Sleep: 10ms, 实际时间: 0.009160s<br>Sleep: 10ms, 实际时间: 0.009321s<br>Sleep: 10ms, 实际时间: 0.009756s<br>Sleep: 10ms, 实际时间: 0.009774s<br>Sleep: 10ms, 实际时间: 0.009496s<br><br>Sleep: 20ms, 实际时间: 0.019757s<br>Sleep: 20ms, 实际时间: 0.019219s<br>Sleep: 20ms, 实际时间: 0.019660s<br>Sleep: 20ms, 实际时间: 0.019316s<br>Sleep: 20ms, 实际时间: 0.019752s<br>Sleep: 20ms, 实际时间: 0.019382s<br>Sleep: 20ms, 实际时间: 0.019410s<br>Sleep: 20ms, 实际时间: 0.019826s<br>Sleep: 20ms, 实际时间: 0.019422s<br>Sleep: 20ms, 实际时间: 0.019424s<br><br>Sleep: 100ms, 实际时间: 0.099853s<br>Sleep: 100ms, 实际时间: 0.099886s<br>Sleep: 100ms, 实际时间: 0.099984s<br>Sleep: 100ms, 实际时间: 0.099611s<br>Sleep: 100ms, 实际时间: 0.099737s<br>Sleep: 100ms, 实际时间: 0.099690s<br>Sleep: 100ms, 实际时间: 0.099351s<br>Sleep: 100ms, 实际时间: 0.099826s<br>Sleep: 100ms, 实际时间: 0.100115s<br>Sleep: 100ms, 实际时间: 0.100057s<br>
 
我的计算机是PII350+Win2k,我的测试结论和楼主的可是不同的<br><br>根据上面的结果,使用Sleep基本还算准确,<br>大多数情况下,操作系统均能提前将Sleep的程序唤醒, 一般不会误事<br><br>个别的Sleep会等待的时间稍长一些,但不会太长
 
用楼主的测试代码也是正常的,难道在不同的计算机上会有不同的表现?
 
to LiChaoHui兄:<br>谢谢您的测试!<br>看来您这里的情况还是比较正常的。<br><br>我的意思确实就是为什么会有机器上的差异?
 
《Delphi深度历险》,里面有详细的说明以及实验和改进的措施<br>请节省点时间吧
 
to journer:请仔细看清我的要求,谢谢!
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
627
import
I
S
回复
0
查看
823
SUNSTONE的Delphi笔记
S
顶部