Vyhledávání na webu

date - setTimeout v JavaScriptu způsobí, že funkce běží rychleji


Mám aplikaci, do které musím vložit hodně hodnot do pole, takže testuji dobu provádění:

var st = new Date().getTime();
var a = [];
for (var i = 0; i < 20971520; i++) {
  a.push(i);
}
var ed = new Date().getTime();
console.info((ed - st) / 1000);
console.info(a.length);

Kódy spouštím přímo v konzoli Firefoxu a konzoli Chrome a trvá to 37 sekund. A během provádění lze dokonce v Chrome pohybovat myší, ale neexistuje žádný interaktivní efekt.

Pak změním kódy:

function push() {
  var st = new Date().getTime();
  var a = [];
  for (var i = 0; i < 20971520; i++) {
    a.push(i);
  }
  var ed = new Date().getTime();
  console.info((ed - st) / 1000);
  console.info(a.length);
}

var tr = setTimeout(push, 50);

Jednoduše dejte kódy do funkce a zavolejte ji pomocí setTimeout, stálo to 0,844 sekundy. A během provádění mohu v Chrome normálně pracovat.

Co se tu děje?

Vím, že setTimeout předá kontrolu prohlížeči, aby vykonal úlohy uživatelského rozhraní, což udělá stránku responzivní. Například když provádím nějaký výpočet během pohybu myši po stránce, provedu výpočet opožděně, aby neblokoval uživatelské rozhraní.

Ale proč to snižuje celkový čas vykonávání stejných kódů?

Odpověď č. 1

A během provádění mohu v Chrome běžně pracovat.

Není pravda. Hlavní okno Chrome bude stejně zamrzlé jako v druhém případě (jen na kratší dobu). Nástroje pro ladění jsou samostatné vlákno a přesto se nezpomalí.

Ale proč to snižuje celkový čas vykonávání stejných kódů?

Platí to, pokud kód spustíte v nástrojích pro vývojáře. Pokud kód skutečně spustíte tam, kde VM může provádět optimalizace vlastností, jsou doby srovnatelné (téměř 1 sekunda). Např.

   var st = new Date().getTime();
   var a = [];
   for (var i = 0; i < 20971520; i++) {
       a.push(i);
   }
   var ed = new Date().getTime();
   console.info('normal', (ed - st) / 1000);
   console.info(a.length);

   function push() {
       var st = new Date().getTime();
       var a = [];
       for (var i = 0; i < 20971520; i++) {
           a.push(i);
       }
       var ed = new Date().getTime();
       console.info('timeout', (ed - st) / 1000);
       console.info(a.length);
   }

   var tr = setTimeout(push, 0);

http://jsfiddle.net/gu9Lg52j/ uvidíte, že normal se spouští stejně rychle jako setTimeout.

Také pokud zabalíte kód do funkce a spustíte ho v konzoli, čas bude srovnatelný i bez setTimeout, protože VM může provádět optimalizace mezi definicí funkce a jejím provedením:

  function push() {
       var st = new Date().getTime();
       var a = [];
       for (var i = 0; i < 20971520; i++) {
           a.push(i);
       }
       var ed = new Date().getTime();
       console.info('timeout', (ed - st) / 1000);
       console.info(a.length);
   }
   push();

Odpověď č. 2

Obě varianty kódu by měly běžet téměř stejně rychle (poslední příklad může být rychlejší, ale ne desetkrát rychlejší).

Uvnitř nástrojů pro vývojáře v Chromu je to jiný příběh. Výrazy jsou vyhodnocovány uvnitř bloku with. To znamená, že proměnné jako a a i jsou nejprve hledány uvnitř jiného objektu ( __commandLineAPI). To přidává další režii, která má za následek desetinásobně delší dobu provádění.