自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

setTimeout的誤差堆積測試和分析

開發(fā) 后端
文章主要是對setTimeout的誤差堆積測試和簡單分析,根據(jù)JS的引擎,setTimeout可能存在一定的時(shí)間誤差,長時(shí)間的誤差堆積將出現(xiàn)較大的偏離值,所以根據(jù)一些例子做了一個(gè)簡單的模擬誤差堆積測試。

前段時(shí)間做了一個(gè)團(tuán)購秒殺倒計(jì)時(shí)的js展現(xiàn)的例子(http://www.blogjava.net/dongbule/archive/2011/12/06/365687.html),倒計(jì)時(shí)的方式主要使用setTimeout的函數(shù)進(jìn)行遞歸實(shí)現(xiàn),由于是使用setTimeout,所以根據(jù)js的引擎,這其中將可能存在一定的時(shí)間誤差,一個(gè)誤差不要緊,兩個(gè)誤差無所謂,但長時(shí)間的誤差堆積將出現(xiàn)較大的偏離值,所以根據(jù)秒殺倒計(jì)時(shí)的例子,做了一個(gè)簡單的模擬的誤差堆積測試,并在各個(gè)瀏覽器中進(jìn)行測試。
鑒于秒殺倒計(jì)時(shí)都是以一秒為單位,所以下面的例子也都以1000毫秒為計(jì)算,當(dāng)然各個(gè)瀏覽器的實(shí)現(xiàn)和附加代碼的編寫也會造成一定的時(shí)間誤差,這部分誤差也合并在setTimeout的實(shí)現(xiàn)里面計(jì)算誤差。

  1. <div id="show" style="width:500px;"></div>  
  2. <script>  
  3. var w = 1000;  
  4. var second = 0;  
  5. function showtime(){      
  6. showtime.curr=  +new Date();      
  7. setTimeout('showtime()',1000);      
  8. document.getElementById("show").innerHTML+=second +"    "+(showtime.curr-(showtime.last||showtime.curr)-1000)+"    <br/>";      
  9. showtime.last=showtime.curr;      
  10. second++;  
  11. }  
  12. showtime();  
  13. </script> 

可以看到在各個(gè)不同的瀏覽器在不同的秒數(shù)中出現(xiàn)不同的誤差,當(dāng)然這個(gè)跟我本機(jī)的瀏覽器和環(huán)境有關(guān)

下面再將這些誤差值進(jìn)行疊加測試

  1. <div>  
  2. <div id="show" style="width:500px;"></div>  
  3. </div>  
  4. <script>  
  5. var w = 1000;  
  6. var i = 0;  
  7. function showtime(){  
  8.     showtime.curr=  +new Date();  
  9.     f = setTimeout('showtime()',1000);  
  10.     w+=(showtime.curr-(showtime.last||showtime.curr)-1000);  
  11.     document.getElementById("show").innerHTML+=i+"   "+(showtime.curr-(showtime.last||showtime.curr)-1000)  +"    "+w+"   
  12.  
  13. <br/>";  
  14.     showtime.last=showtime.curr;  
  15.     i++;  
  16. }  
  17. showtime();  
  18. </script> 

 

IE和chrome相對較為穩(wěn)定,不知道是不是我本機(jī)環(huán)境的原因,firefox出現(xiàn)了很多大偏差,可以選擇定時(shí)清空這個(gè)誤差值來處理,或是采用鏈?zhǔn)降膕etTimeOut()來處理。

  1. <div id="show" style="width:300px;"></div>  
  2. <script>  
  3. var w = 1000;  
  4. var i = 0;  
  5. var f ;  
  6. var t ;  
  7. var k = 0;  
  8. function showtime(){  
  9.     showtime.curr=  +new Date();  
  10.     f = setTimeout('showtime()',1000);  
  11.     w+=(showtime.curr-(showtime.last||showtime.curr)-1000);  
  12.     document.getElementById("show").innerHTML+=i+"   "+w+"  "+(showtime.curr-(showtime.last||showtime.curr)-1000)  +"    <br/>";  
  13.     showtime.last=showtime.curr;  
  14.     i++;  
  15. }  
  16. function round(){  
  17.     if(k!=0){  
  18.         clearTimeout(f);  
  19.         showtime();  
  20.         document.getElementById("show").innerHTML+="  clear<br/>";  
  21.         w=0;  
  22.     }  
  23.     setTimeout('round()',10000);  
  24.     k++;  
  25. }  
  26. showtime();  
  27. round();  
  28. </script> 

其實(shí)為什么javascript的定時(shí)器會出現(xiàn)所謂的不可靠或偏差的情況,這是可以理解的,最主要的問題是它們并不是所謂的線程,其實(shí)
javascript是運(yùn)行于單線程的環(huán)境中,而定時(shí)器只是計(jì)劃代碼在未來某個(gè)執(zhí)行的時(shí)間,執(zhí)行的時(shí)間點(diǎn)是不能被保證的,因?yàn)樵陧撁娴纳芷谥?,不同時(shí)間可能存在其他代碼,或各個(gè)瀏覽器的內(nèi)核控制住javascript進(jìn)程。

settimeout幾個(gè)見解

1、setTimeOut != thread | 時(shí)間片的并發(fā)調(diào)用

2、javascript以單線程的方式運(yùn)行于瀏覽器的javascript引擎中

3、setTimeout 只是把要執(zhí)行的代碼在設(shè)定的時(shí)間點(diǎn)插入js引擎維護(hù)的代碼隊(duì)列

4、setTimeout 插入代碼隊(duì)列并不意味著代碼就會立馬執(zhí)行的

  1. function showtime(){  
  2. // code 1...  
  3. f = setTimeout('showtime()',200); //200毫秒后要插入執(zhí)行代碼對瀏覽器的js隊(duì)列  
  4. // code 2...  

以上面面的代碼為例,說說它的執(zhí)行流程

Code 1 -> 200毫秒后通知瀏覽器有隊(duì)列插入 -> Code 2 -> showtime() -> …

這個(gè)種重復(fù)遞歸可能會造成2個(gè)問題:

1 . 時(shí)間間隔可能小于定時(shí)調(diào)用的代碼的執(zhí)行時(shí)間

2 . 時(shí)間間隔或許會跳過

5ms : code1 代碼執(zhí)行完畢,200ms后有定時(shí)器進(jìn)入隊(duì)列

205ms : 定時(shí)器進(jìn)入隊(duì)列,code2繼續(xù)

300ms : function代碼結(jié)束,定時(shí)器從隊(duì)列中取出,執(zhí)行

405ms : 第二個(gè)定時(shí)器進(jìn)入隊(duì)列,第一個(gè)定時(shí)器的代碼在執(zhí)行中

605ms : 第三個(gè)定時(shí)器意圖進(jìn)入隊(duì)列失敗,這個(gè)點(diǎn)的settimeout丟失

為了避免這2個(gè)問題,可以采用鏈?zhǔn)絪etTimeOut()進(jìn)行調(diào)用

  1. setTimeOut(function(){  
  2. code處理...  
  3. setTimeOut(arguments.callee,interval);  
  4. },interval); 

這個(gè)模式鏈?zhǔn)綏l用setTimeOut(),每次函數(shù)執(zhí)行的時(shí)候都會創(chuàng)建一個(gè)新的定時(shí)器,第二個(gè)setTimeOut調(diào)用使用了arguments.callee來獲取當(dāng)前執(zhí)行的函數(shù)引用,并為其設(shè)置另外一個(gè)定時(shí)器,這樣的好處在于,在前一個(gè)定時(shí)器執(zhí)行完之前不會向隊(duì)列中插入新的定時(shí)器代碼,確保不會有任何的確實(shí)間隔,而且它可以保證在下一次定時(shí)器代碼執(zhí)行前,至少等待指定的間隔,避免連續(xù)的運(yùn)行。

秒殺的定時(shí)器已經(jīng)通過檢測正式運(yùn)行了,博客記錄得不好,表達(dá)不是很清楚,關(guān)于setTimeOut的函數(shù)主要參考了《JavaScript高級程序設(shè)計(jì)(第2版)》的第18章。

原文鏈接:http://www.blogjava.net/dongbule/archive/2012/01/10/368229.html

【編輯推薦】

  1. 一個(gè)Java程序員對2011年的回顧
  2. 用Java GUI編寫的畫板程序
  3. Java的動態(tài)綁定機(jī)制
  4. Java中帶復(fù)選框的樹的實(shí)現(xiàn)和應(yīng)用
  5. Java網(wǎng)絡(luò)編程菜鳥進(jìn)階:TCP和套接字入門
責(zé)任編輯:林師授 來源: 于吉吉的博客
相關(guān)推薦

2019-11-12 11:15:39

setTimeout前端代碼

2023-11-01 10:18:10

自動化測試工具

2021-11-08 15:38:15

消息延遲堆積

2023-03-29 10:19:44

異步編程AsyncPromise

2022-11-08 07:36:17

RocketMQ消費(fèi)者消息堆積

2024-10-16 08:36:03

2011-05-16 14:54:12

測試用例

2011-06-14 14:43:03

灰盒測試

2011-05-31 14:33:53

settimeout

2010-05-27 11:44:37

2023-09-18 16:14:35

性能測試開發(fā)

2011-02-23 11:18:48

MongoDBMySQL性能測試

2023-12-21 08:01:41

RocketMQ消息堆積

2010-03-05 10:31:24

Ubuntu PHP

2011-06-14 09:12:03

JavaScript

2021-01-13 10:51:08

PromissetTimeout(函數(shù)

2025-01-08 08:47:44

Node.js內(nèi)存泄露定時(shí)器

2011-05-16 14:24:02

軟件測試

2021-11-23 09:00:59

消息堆積擴(kuò)容RocketMQ

2023-05-12 07:38:46

Python基準(zhǔn)測試性能分析
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號