2012-02-15 15 views
9

Zamana duyarlı bir projede çalışırken, zamanlama olaylarının ayrıntı düzeyini, önce masaüstü bilgisayarımda Firefox'ta, sonra Linux sunucumda node.js kodu olarak test etmek için aşağıdaki kodu kullandım. Firefox koşulu, 1ms zaman aşımına göre 200 fps ortalamaya ulaşan ve 5 ms'lik granüliteyle zamanlama olaylarım olduğunu gösteren tahmin edilebilir sonuçlar üretti.node.js neden setTimeout (func, 1.0) ayarını yanlış yapıyor?

Şimdi, zaman aşımı değeri 0 olarak kullanılırsa, Node.js Chrome V8 motoru temel olarak zaman aşımını bir etkinliğe devretmeyecek, ancak hemen işleyeceğini biliyorum. Beklendiği gibi, rakamlar, net olarak CPU kapasitesinde (ve üstü ile doğrulanmış) işlem gören 60.000 fps ortalamaya ulaştı. Ancak 1 ms zaman aşımı ile sayıları hala saniyede 3.5-4 bin devir() idi, bu da Node.js'nin saniyede teorik olarak maksimum 1 bin devir yaratacağı 1 ms zaman aşımına uymadığı anlamına geliyor. Bir sayı aralığı ile oynamak

, alıyorum:

  • 2ms: ~ 100 fps (gerçek zaman aşımı, Linux üzerinde zamanlama olayların 10ms parçalı yapı gösteren)
  • 1.5:
  • 1,0001 aynı: Aynı
  • 1.0: 3.500 - 4.500 fps
  • 0.99: 2.800 - 3600 fps
  • 0.5: 1.100 - 2.800 fps
  • 0.0001: 1.800 - 3.300 fps
  • 0.0: ~ 60,000 fps

ECMAScript özellikleri muhtemelen gerçek bir çağrı devretme setTimout hiç söz verir, çünkü setTimeout davranışı (işlev, 0), mazur görünmektedir OS düzeyinde kesinti. Ancak 0 < = < = 1.0 herhangi bir şeyin sonucu açıkça gülünç. Gecikmesi için belli bir süre verdim ve x gecikmesi için teorik minimum süre (n-1) * x olmalıdır. V8/Node.js ne yapıyor? node.js api docs for setTimeout(cb, ms) (vurgu mayın) Gönderen

var timer, counter = 0, time = new Date().getTime(); 

function cycle() { 
    counter++; 
    var curT = new Date().getTime(); 
    if(curT - time > 1000) { 
     console.log(counter+" fps"); 
     time += 1000; 
     counter = 0; 
    } 
    timer = setTimeout(cycle, 1); 
} 

function stop() { 
    clearTimeout(timer); 
} 

setTimeout(stop, 10000); 
cycle(); 
+0

Ne ben tahmin ediyorum node.js ekibin en kısa sürede 'anlamında bir zaman aşımı değeri olarak 1' 'kullanılan vahşi kod gözlenen olmasıdır. Programcıların (ben dahil) birçoğunun 'setTimeout (someFunc, 0) 'yazarken tereddüt ettiklerini biliyorum, çünkü' 0 'bir şekilde' yanlış geliyor 'burada ... Sıfır zaman aşımı zaman aşımı değildir. '1', bu kodda ASAP anlamına gelecek bir sonraki mantıksal değer gibi görünüyor. Bu nedenle Node.js kodunun muhtemelen bir denetimi vardır, örneğin (timeout> 1) {scheduleTimeout (bazıFunc, timeout);} else {scheduleNextTick (someFunc);} ' –

+0

Çok ilginç bir soru BTW. Bu tür bir araştırmayı çok seviyorum! –

cevap

1

Bütünlüğü için ben nodeJS uygulanmasına işaret etmek istiyorum:

https://github.com/nodejs/node-v0.x-archive/blob/master/lib/timers.js#L214

hangisi:

BOŞTA

zaman aşımları:

// Timeout values > TIMEOUT_MAX are set to 1. 
var TIMEOUT_MAX = 2147483647; // 2^31-1 
... 
exports.setTimeout = function(callback, after) { 
    var timer; 

    after *= 1; // coalesce to number or NaN 

    if (!(after >= 1 && after <= TIMEOUT_MAX)) { 
     after = 1; // schedule on next tick, follows browser behaviour 
    } 

    timer = new Timeout(after); 
    ... 
} 

Bu ifadeyi hatırla

Sık sık birçok soket aynı boşta kalma zaman aşımına sahip olacağından, öğe başına bir zaman aşımı denetçisi kullanmayacağız. Çok fazla havai.
Bunun yerine, aynı zaman aşımı değeri ve bağlantılı bir listeyle tüm soketler için tek bir izleyici kullanacağız.

Bu teknik libev kılavuzunda açıklanmaktadır: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be_smart_about_timeouts

Ve biz burada same timeout value (1) geçmektedir.

Timer için uygulama

buradadır:
https://github.com/nodejs/node-v0.x-archive/blob/master/src/timer_wrap.cc

+0

Geriye baktığımda, 0 HonoredMule

5

:

Tam milisaniye geciktirmek da geri arama muhtemelen denilen olmayacak unutulmamalıdır - node.js hakkında hiçbir garanti vermez Geri çağırma ne zaman tam zamanlama, ne sipariş sıraları ateş edecektir. Geri arama belirtilen süre mümkün olduğunca yakın çağrılacak.

ben "mümkün olduğunca yakın" Size daha uygulama ekibine farklı bir şey anlamına geldiğini varsayalım.

[Düzenleme] Bu arada, setTimeout() function (apparently part of the HTML5 draft rağmen) bir tarifname tarafından zorunlu olduğu görülmektedir. Dahası, 4-10 ms de-facto asgari düzeyde taneciklik seviyesi var gibi gözüküyor, bu yüzden de "nasıl olduğu" gibi görünüyor.

Açık kaynaklı yazılımlar ile ilgili en iyi şey, ihtiyaçlarınız doğrultusunda daha yüksek bir çözünürlük eklemek için bir yamaya katkıda bulunabilmenizdir!

+0

@HonoredMule: bu rakamlar beklentilerinizden dolayı veya yazılımın nasıl uygulandığına dair özelliklerinden dolayı "hiç anlam ifade etmiyor". – maerics

+0

Ayrıca, setInterval yalnızca aralık node.js'de> = 1,0 ise çalışır ve her zaman her yerde gerçek bir kesinti gibi görünür, Linux'ta 5ms tanecikligi ve Firefox'ta 4 ms'lik granülarite gösterir. OS seviyesinde kesinti granülaritesinin merhametinde olduğumuz zaman "garantiler" olayı beklenir, ancak bu saniyede 4,000 kesintiye yol açmaz. Aradığım şey/node.js'nin bir API seviyesinden yaptığı bir açıklamadır (yani 0 => acil çağrı, <= 1.0 => doğrudan Node'un olay sırasına,> 1.0 => doğru kesme). Belgeler hiçbir şey söylemiyor. – HonoredMule

+0

Maalesef, ilk yorumu olduğu gibi göndermek istemedim (paragrafın kesilmesini istedim) - Düzenleme zamanından çıktıktan sonra onu sildim. Her neyse, beklentilerimin daha ayrıntılı bir dökümantasyon olmadan ayarlanması zordur ... dolayısıyla soru. – HonoredMule

İlgili konular