Geri aramalarla JavaScript kodunun yürütme süresini nasıl ölçebilirim?


319

node.jsTercüman kullanarak yürüttüğüm bir JavaScript kodu parçası var .

for(var i = 1; i < LIMIT; i++) {
  var user = {
    id: i,
    name: "MongoUser [" + i + "]"
  };
  db.users.save(user, function(err, saved) {
    if(err || !saved) {
      console.log("Error");
    } else {
      console.log("Saved");
    }
  });
}

Bu veritabanı ekleme işlemleri tarafından harcanan zamanı nasıl ölçebilirim? Bu kod parçasından önce ve sonra tarih değerleri farkını hesaplayabilirim ama kodun eşzamansız yapısı nedeniyle bu yanlış olur.


8
Sadece db çağrısından önce başlangıç ​​zamanını ve geri
— aramanın İÇİNDEKİ

DB'nin ekleme işlemini bitirdiği zaman ve geri aramanın yürütüldüğü zaman aynı değildir ve bu ölçümde bir hataya neden olabilir mi?
— Stormshadow

1
Hayır, bu konuda endişelenmemelisiniz, db kütüphane kodu iyi tasarlanmışsa ve geri çağrıyı tetiklemeden önce başka bir işlem yapmıyorsa, iyi bir önlem almalısınız.
— Eklemeyi

Yapmaya çalıştığınız şey için iyi bir uyum gibi görünen NodeTime'ı denemenizi tavsiye ederim .
— Julian Knight

Ben timerlogbenzer olan console.time()ama ek özellikleri ile yazdı ; github.com/brillout/timerlog
— brillout

Yanıtlar:


718

Node.js dosyasını kullanın console.time()ve console.timeEnd():

var i;
console.time("dbsave");

for(i = 1; i < LIMIT; i++){
    db.users.save({id : i, name : "MongoUser [" + i + "]"}, end);
}

end = function(err, saved) {
    console.log(( err || !saved )?"Error":"Saved");
    if(--i === 1){console.timeEnd("dbsave");}
};

31
Düğüm için temiz ve yerleşik çözüm.
— Behlül Uçar

45
> Bu db insert işlemleri tarafından geçen sürenin nasıl ölçüleceğini bilmek istiyorum. --- console.timeEnd ("dbsave") sadece zamanlamayı konsollamak için çıktı verir. Bunu daha fazla kullanamazsınız ve daha az esnektir. Gerçek zamanlama değerine ihtiyacınız varsa, orijinal sorudaki gibi, console.timeEnd ("dbsave")
— gogaman

@gogaman bu iyi bir noktadır, çünkü console.timeEnd () öğesinden çıktı çekemezsiniz. Çıktıyı bir dosyaya bağlamak ve oradan faydalanmak faydalı olabilir.
— Doug Molineux

5
Peki aşağıdaki cevapta console.time () ve process.hrtime () arasındaki fark nedir?
— yellow-saint

3
Şimdi yeni kullanıcıların şimdi, böylece yürütme süresi yazdırılır bir not eklemeye değer.
— janko-m

208

Bunun için tasarlanmış bir yöntem var. Check out ) (process.hrtime;.

Yani, temelde bunu uygulamamın en üstüne koydum.

var start = process.hrtime();

var elapsed_time = function(note){
    var precision = 3; // 3 decimal places
    var elapsed = process.hrtime(start)[1] / 1000000; // divide by a million to get nano to milli
    console.log(process.hrtime(start)[0] + " s, " + elapsed.toFixed(precision) + " ms - " + note); // print message + time
    start = process.hrtime(); // reset the timer
}

Sonra fonksiyonların ne kadar sürdüğünü görmek için kullanıyorum. "Output.txt" adlı bir metin dosyasının içeriğini bastıran temel bir örnek:

var debug = true;
http.createServer(function(request, response) {

    if(debug) console.log("----------------------------------");
    if(debug) elapsed_time("recieved request");

    var send_html = function(err, contents) {
        if(debug) elapsed_time("start send_html()");
        response.writeHead(200, {'Content-Type': 'text/html' } );
        response.end(contents);
        if(debug) elapsed_time("end send_html()");
    }

    if(debug) elapsed_time("start readFile()");
    fs.readFile('output.txt', send_html);
    if(debug) elapsed_time("end readFile()");

}).listen(8080);

İşte bir terminalde (BASH kabuğu) çalıştırabileceğiniz hızlı bir test:

for i in {1..100}; do echo $i; curl http://localhost:8080/; done

3
herhangi bir şekilde console.time çözümüne üstün mü?
— scravy

31
Evet, çok daha kesin ve sonucu bir değişkende saklayabilirsiniz
— Dallas Clark

Zamanlayıcıyı birkaç kez aramak istediğim için bu benim için çalışıyor
— tbh__

2
Neden process.hrtime(start)iki kez araıyorsun? Bunun özel bir nedeni var mı?
— Sohail Si

1
process.hrtime ([time]); burada saat, geçerli zamana göre farklılık göstermesi için önceki bir process.hrtime () çağrısının sonucu olması gereken isteğe bağlı bir parametredir. Geçerli çağrı ile önceki hrtime çağrısı arasındaki farkı verir.
— Nilesh Jain

72

Çağırma console.time('label'), geçerli saati milisaniye olarak kaydeder ve daha sonra ararconsole.timeEnd('label') , o noktadan itibaren süreyi görüntüler.

Milisaniye cinsinden süre otomatik olarak etiketin yanına yazdırılır, böylece bir etiket yazdırmak için console.log dosyasına ayrı bir çağrı yapmanız gerekmez:

console.time('test');
//some code
console.timeEnd('test'); //Prints something like that-> test: 11374.004ms

Daha fazla bilgi için Mozilla'nın geliştirici belgelerineconsole.time bakın .



1
Kabul edilen cevap, kodumu kullanma
— cevabımdan

24

Kimse henüz yeni inşa edilmiş kütüphanelerden bahsetmemişti:

Düğüm> = 8.5'de bulunur ve Modern Tarayıcılarda olmalıdır

https://developer.mozilla.org/en-US/docs/Web/API/Performance

https://nodejs.org/docs/latest-v8.x/api/perf_hooks.html#

Düğüm 8.5 ~ 9.x (Firefox, Chrome)

// const { performance } = require('perf_hooks'); // enable for node
const delay = time => new Promise(res=>setTimeout(res,time))
async function doSomeLongRunningProcess(){
  await delay(1000);
}
performance.mark('A');
(async ()=>{
  await doSomeLongRunningProcess();
  performance.mark('B');
  performance.measure('A to B', 'A', 'B');
  const measure = performance.getEntriesByName('A to B')[0];
  // firefox appears to only show second precision.
  console.log(measure.duration);
  performance.clearMeasures(); // apparently you should remove entries...
  // Prints the number of milliseconds between Mark 'A' and Mark 'B'
})();

https://repl.it/@CodyGeisler/NodeJsPerformanceHooks

Düğüm 10.x

https://nodejs.org/docs/latest-v10.x/api/perf_hooks.html

const { PerformanceObserver, performance } = require('perf_hooks');
const delay = time => new Promise(res => setTimeout(res, time))
async function doSomeLongRunningProcess() {
    await delay(1000);
}
const obs = new PerformanceObserver((items) => {
    console.log('PerformanceObserver A to B',items.getEntries()[0].duration);
    performance.clearMarks();
});
obs.observe({ entryTypes: ['measure'] });

performance.mark('A');

(async function main(){
    try{
        await performance.timerify(doSomeLongRunningProcess)();
        performance.mark('B');
        performance.measure('A to B', 'A', 'B');
    }catch(e){
        console.log('main() error',e);
    }
})();

TypeError: performance.getEntriesByName is not a functionDüğüm v10.4.1
— Jeremy Thille

Örneği ben çevrimiçi çalıştırabilmeniz için yaptım. Düğüm 9.7.1'dir. Eğer v10.4.1'de çalışmıyorsa, neyin değişebileceğini merak ediyorum!
— Cody G

1
Stability: 1 - Experimentalolabilir? :) nodejs.org/docs/latest-v8.x/api/…
— Jeremy Thille

Evet, kesinlikle değişti. V10'da yeni bir gözlemci var, belgeleri nodejs.org/docs/latest-v10.x/api/documentation.html adresinde görebilirsiniz . Şansım olduğunda güncelleme yapacağım!
— Cody G

19

Konsol çıktısı yerine zaman geçen değeri almak isteyen herkes için:

@ D.Deriso önerisi olarak process.hrtime () kullanın , aşağıda benim daha basit yaklaşımım:

function functionToBeMeasured() {
    var startTime = process.hrtime();
    // do some task...
    // ......
    var elapsedSeconds = parseHrtimeToSeconds(process.hrtime(startTime));
    console.log('It takes ' + elapsedSeconds + 'seconds');
}

function parseHrtimeToSeconds(hrtime) {
    var seconds = (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3);
    return seconds;
}

16
var start = +new Date();
var counter = 0;
for(var i = 1; i < LIMIT; i++){
    ++counter;
    db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
          if( err || !saved ) console.log("Error");
          else console.log("Saved");
          if (--counter === 0) 
          {
              var end = +new Date();
              console.log("all users saved in " + (end-start) + " milliseconds");
          }
    });
}

5
Bunun ne anlama geldiğini anlamak için '+ new Date ()' sözdizimini aramak zorunda kaldım. Bu cevaptaki yorumlara ( stackoverflow.com/a/221565/5114 ) göre, bu formu performans nedenlerinin yanı sıra okunabilirlik için kullanmak iyi bir fikir değildir. Biraz daha ayrıntılı bir şey tercih ediyorum, bu yüzden okuyucu için daha net. Ayrıca bu cevaba da bakınız: stackoverflow.com/a/5036460/5114
— Mnebuerquo

3
Sık sık var start = process.hrtime(); ... var end = process.hrtime(start);yüksek çözünürlük süresi elde etmek için kullanıyorum (milisaniyenin altında doğruluk beklemem gerekirse)
— Andrey Sidorov

9

Eski soru ama basit bir API ve hafif çözüm için; dahili olarak yüksek çözünürlüklü gerçek zamanlı ( ) kullanılan perfy kullanabilirsiniz process.hrtime.

var perfy = require('perfy');

function end(label) {
    return function (err, saved) {
        console.log(err ? 'Error' : 'Saved'); 
        console.log( perfy.end(label).time ); // <——— result: seconds.milliseconds
    };
}

for (var i = 1; i < LIMIT; i++) {
    var label = 'db-save-' + i;
    perfy.start(label); // <——— start and mark time
    db.users.save({ id: i, name: 'MongoUser [' + i + ']' }, end(label));
}

Her seferinde perfy.end(label) çağrıldığında bu örneğin otomatik olarak imha edildiğini unutmayın.

Açıklama: D.Deriso'nun cevabından esinlenerek bu modülü yazdı . Dokümanlar burada .


2

Sen verebilir Benchmark.js bir deneyin. Ayrıca aralarında birçok platformu da destekler.


11
Bu kullanım durumu için benchmark.js'nin nasıl kullanılacağına dair bir örnek ekleyebilmeniz iyi olur.
— Petah

2

Ayrıca exectimer deneyebilirsiniz . Size aşağıdaki gibi geri bildirim sağlar:

var t = require("exectimer");

var myFunction() {
   var tick = new t.tick("myFunction");
   tick.start();
   // do some processing and end this tick
   tick.stop();
}

// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.myFunction.min()); // minimal tick duration
console.log(t.timers.myFunction.max()); // maximal tick duration
console.log(t.timers.myFunction.mean()); // mean tick duration
console.log(t.timers.myFunction.median()); // median tick duration

[değiştir] Şimdi exectimer kullanmak için daha basit bir yolu var çünkü şimdi ölçülecek kodu sarabilir. Kodunuz şu şekilde sarılabilir:

var t = require('exectimer'),
Tick = t.Tick;

for(var i = 1; i < LIMIT; i++){
    Tick.wrap(function saveUsers(done) {
        db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
            if( err || !saved ) console.log("Error");
            else console.log("Saved");
            done();
        });
    });
}

// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.saveUsers.min()); // minimal tick duration
console.log(t.timers.saveUsers.max()); // maximal tick duration
console.log(t.timers.saveUsers.mean()); // mean tick duration
console.log(t.timers.saveUsers.median()); // median tick duration


0

Başka bir seçenek de hızlı hata ayıklama aracını kullanmaktır:

express-debug, express için bir geliştirme aracıdır. Engelsiz bir şekilde html'nize yararlı hata ayıklama çıktısı enjekte eden basit ara katman yazılımıdır.

Uygun şekilde bir profil oluşturma paneli sunar:

toplam talep işleme süresi. ara katman yazılımı, param ve rota zamanlamaları.

Ayrıca. Yukarıdaki yanıtlara eklemek için, yalnızca geliştirme ortamı için profil oluşturma kodunu etkinleştirmek üzere bu yanıtı kontrol edebilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.