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.