Jak zmierzyć czas potrzebny na wykonanie funkcji


1188

Potrzebuję uzyskać czas wykonania w milisekundach.

Pierwotnie zadałem to pytanie w 2008 r. Przyjęta odpowiedź polegała na użyciu nowej funkcji Date (). GetTime () Jednak wszyscy możemy teraz zgodzić się, że użycie standardowego interfejsu API performance.now () jest bardziej odpowiednie. Dlatego zmieniam przyjętą odpowiedź na to pytanie.


3
Często oświadczenie o tym, co próbujesz osiągnąć dzięki czasowi wykonania, może okazać się o wiele bardziej przydatne niż samo udzielenie odpowiedzi na pytanie. Obecnie korzystanie z narzędzi do profilowania w Firebug lub Chrome Dev jest często znacznie lepszym sposobem na znalezienie kodu zasysającego sok z procesora.
oligofren,

oto jak możesz to zrobić w klasyczny Datesposób, który daje ci msi wystarcza w większości przypadków. Myślę, że albertech.blogspot.com/2015/07/ ... ... ale tak, naprawdę powinieneś na to spojrzećPerformance.now
słój

5
performance.now()nie działa w węźle. new Date().getTime()będzie działać w węźle.
Ryan Walker,

1
numer 1000 upvote woop woop: D
Kiksen

1
@oligofren - Czasami możesz chcieć przechwycić te dane. Mam sytuacji gdzie ja piszę to do IndexedDB
ThomasRones

Odpowiedzi:


1753

Za pomocą performance.now () :

var t0 = performance.now()

doSomething()   // <---- The function you're measuring time for 

var t1 = performance.now()
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")

NodeJs: wymagane jest zaimportowanieperformance klasy


Za pomocą konsoli. Czas :(niestandardowy)( standard życia )

console.time('someFunction')

someFunction() // Whatever is timed goes between the two "console.time"

console.timeEnd('someFunction')

Uwaga :
Ciąg znaków przekazywany dometodtime()itimeEnd()musi być zgodny
(aby licznik czasu zakończył się zgodnie z oczekiwaniami).

console.time() dokumentacje:

  1. Dokumentacja NodeJS dotycząca
  2. Dokumentacja MDN (po stronie klienta)

27
Jest teraz obsługiwany także przez Narzędzia programistów Chrome.
julien_c

3
Jest to obecnie najlepszy sposób na zebranie dokładnych czasów z tego, co rozumiem.
Ash Blue

6
Czy nie musisz wykonywać funkcji między tymi dwiema instrukcjami? Teraz mierzysz czas potrzebny do jego zdefiniowania, a nie wykonania. Popraw mnie, jeśli się mylę ...
Cristian

2
Link do artykułu MDN na temat tej funkcji: developer.mozilla.org/en-US/docs/DOM/console.time
nullability

6
tak, możesz zrobić `totalTime + = console.timeEnd ('timer') 'i zrobić to dla każdego timera
vsync

637

użyj nowej Date (). getTime ()

Metoda getTime () zwraca liczbę milisekund od północy 1 stycznia 1970 r.

dawny.

var start = new Date().getTime();

for (i = 0; i < 50000; ++i) {
// do something
}

var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time);

9
Zauważ, że możesz zastąpić + new Date () wywołaniem getTime (): var start = + new Date (); // zrób alert rzeczy („Czas wykonania:” + (+ nowa data ()) - start);
J c

55
Czasy nie są dokładne, ponieważ data nie jest przeznaczona dla tej funkcji. Będę tu śmiały i powiem, że powinieneś użyć przykładu vsync, jeśli chcesz dokładnego pomiaru czasu. Chociaż działa tylko w bankomatach Chrome i Firefox.
Ash Blue

9
Uważaj, getMilliseconds () podaje ułamek milisekundowy bieżącego sekundy. Jeśli zamienisz getTime () na getMilliseconds (), możesz uzyskać negatywne wyniki, jeśli przekroczysz sekundę.
RickyA,

6
Odpowiedź vsync jest o wiele bardziej poprawna według dzisiejszych standardów, a użycie Date () może powodować wyświetlanie bardzo błędnych wyników, szczególnie na platformie Windows, gdzie wyniki mogą być zaokrąglane + wyświetlane do najbliższej granicy 15 ms, co powoduje dziwne rzeczy, takie jak 0ms taktowania na małych bitach kodu.
oligofren,

29
@AshBlue, powinniśmy użyć window.performance.now. Patrz stackoverflow.com/a/15641427/632951
Pacerier

405

Nie używaj Date (). Czytaj poniżej.

Użyjperformance.now() :

<script>
var a = performance.now();
alert('do something...');
var b = performance.now();
alert('It took ' + (b - a) + ' ms.');
</script>

Działa na:

  • IE 10 ++

  • FireFox 15 ++

  • Chrome 24 ++

  • Safari 8 ++

  • Opera 15 ++

  • Android 4.4 ++

  • itd itd

console.timemoże być dla Ciebie opłacalny , ale jest to niestandardowe § :

Ta funkcja jest niestandardowa i nie jest na standardowym torze. Nie używaj go w witrynach produkcyjnych z dostępem do Internetu: nie będzie działać dla każdego użytkownika. Nie mogą być również duże niezgodności między wdrożeń oraz zachowanie może się zmienić w przyszłości.

Oprócz obsługi przeglądarki performance.nowwydaje się, że może ona zapewniać dokładniejsze czasy, ponieważ wydaje się, że jest to wersja gołe kości console.time.


<rant> Ponadto, NIGDY nie używaj Datedo niczego, ponieważ wpływają na to zmiany „czasu systemowego”. Co oznacza, że będzie się nieprawidłowe wyniki -jak „negatywnej czasu” - gdy użytkownik nie posiada dokładny czas systemowy:

W październiku 2014 r. Mój zegar systemowy zwariował i zgadnij, co ... Otworzyłem Gmaila i zobaczyłem wszystkie e-maile z mojego dnia „wysłane 0 minut temu ”. I myślałem, że Gmail powinien być zbudowany przez światowej klasy inżynierów z Google .......

(Ustaw zegar systemowy na rok temu i przejdź do Gmaila, abyśmy wszyscy mogli się dobrze pośmiać. Być może pewnego dnia będziemy mieli Salę Wstydu dla JS Date.)

now()Problem dotyczy także funkcji arkusza kalkulacyjnego Google .

Używasz Datetylko wtedy, gdy chcesz pokazać użytkownikowi jego czas systemowy. Nie wtedy, gdy chcesz uzyskać na czas lub do środka niczym.


3
Właśnie tego szukałem! Chcę być w stanie dodać kilka razy razem, tak naprawdę nie mogę tego zrobić z czasami konsoli.
Ray

8
zauważ, że nie jest to jeszcze obsługiwane w safari: developer.mozilla.org/en-US/docs/Web/API/Performance.now ()
Akos K

2
Używam Firebug Profile i performance.now () i oba działają dobrze. Performance.now () potwierdza mój wynik z profilu.
Vincent Jia,

2
Nie działa w moim największym zawieszeniu, którym jest IE7 (klienci korporacyjni). Nie dbam o pomiar wydajności w chrome, zawsze jest błyskawiczny.
Nick

2
Jest to lepszy sposób niż console.time ().
Sanjeev

52

Jeśli potrzebujesz uzyskać czas wykonania funkcji na lokalnym komputerze programistycznym , możesz użyć narzędzi profilujących przeglądarki lub poleceń konsoli, takich jak console.time()i console.timeEnd().

Wszystkie nowoczesne przeglądarki mają wbudowane profile JavaScript. Profile te powinny dać najdokładniejszy pomiar, ponieważ nie trzeba modyfikować istniejącego kodu, co może wpłynąć na czas wykonywania funkcji.

Aby profilować JavaScript:

  • W Chrome naciśnij klawisz F12 i wybierz kartę Profile , a następnie Zbierz profil procesora JavaScript .
  • W przeglądarce Firefox zainstaluj / otwórz Firebug i kliknij przycisk Profil .
  • W przeglądarce IE 9+ naciśnij klawisz F12 , kliknij Skrypt lub Profiler (w zależności od wersji IE).

Alternatywnie na komputerze programistycznym możesz dodać oprzyrządowanie do kodu za pomocą console.time()i console.timeEnd(). Funkcje te, obsługiwane w Firefox11 +, Chrome2 + i IE11 +, raportują liczniki czasu, za pomocą których uruchamiasz / zatrzymujesz console.time(). time()przyjmuje jako argument nazwę zdefiniowanego przez użytkownika timera, a timeEnd()następnie raportuje czas wykonania od uruchomienia timera:

function a() {
  console.time("mytimer");
  ... do stuff ...
  var dur = console.timeEnd("myTimer"); // NOTE: dur only works in FF
}

Pamiętaj, że tylko Firefox zwraca upływ czasu timeEnd()połączenia. Inne przeglądarki po prostu zgłaszają wynik do konsoli programisty: zwracana wartość parametru timeEnd()jest niezdefiniowana.

Jeśli chcesz uzyskać czas wykonywania funkcji na wolności , musisz instrumentować swój kod. Masz kilka opcji. Możesz po prostu zapisać czas rozpoczęcia i zakończenia, wysyłając zapytanie new Date().getTime():

function a() {
  var start = new Date().getTime();
  ... do stuff ...
  var end = new Date().getTime();
  var dur = end - start;
}

Jednak Dateobiekt ma rozdzielczość tylko milisekundową i będą podlegały zmianom zegara systemowego dowolnego systemu operacyjnego. W nowoczesnych przeglądarkach jest lepsza opcja.

Lepszą opcją jest użycie czasu wysokiej rozdzielczości , alias window.performance.now(). now()jest lepszy niż tradycyjny Date.getTime()na dwa ważne sposoby:

  1. now()jest podwójną z rozdzielczością submilisekundową, która reprezentuje liczbę milisekund od początku nawigacji strony. Zwraca liczbę mikrosekund w ułamku (np. Wartość 1000,123 to 1 sekunda i 123 mikrosekundy).

  2. now()rośnie monotonicznie. Jest to ważne, ponieważ Date.getTime()może ewentualnie skoczyć do przodu lub do tyłu nawet na kolejnych połączeń. W szczególności, jeśli czas systemowy systemu operacyjnego zostanie zaktualizowany (np. Synchronizacja zegara atomowego), Date.getTime()również zostanie zaktualizowany. now()gwarantuje, że zawsze będzie monotonicznie wzrastać, więc czas systemowy systemu operacyjnego nie ma na niego wpływu - zawsze będzie to zegar ścienny (zakładając, że zegar ścienny nie jest atomowy ...).

now()mogą być stosowane w niemal każdym miejscu, które new Date().getTime(), + new Dateandt Date.now()znajdują. Wyjątkiem jest to, że Datei now()czasy nie mieszać, a Dateopiera się na Unix epoki (liczba milisekund od 1970 roku), podczas gdy now()jest to liczba milisekund od rozpoczęła swoją nawigację strony (tak, to będzie dużo mniejszy niż Date).

Oto przykład użycia now():

function a() {
  var start = window.performance.now();
   ... do stuff ...
  var end = window.performance.now();
  var dur = end - start;
}

now()jest obsługiwany w przeglądarce Chrome stabilnej, Firefox 15+ i IE10. Dostępnych jest również kilka wypełniaczy .

Inną opcją pomiaru czasu wykonania na wolności jest UserTiming . Funkcja UserTiming zachowuje się podobnie do console.time()i console.timeEnd(), ale wykorzystuje ten sam znacznik czasu wysokiej rozdzielczości, z którego now()korzysta (dzięki czemu otrzymujesz monotonicznie rosnący zegar poniżej jednej milisekundy), a także zapisuje znaczniki czasu i czas trwania w PerformanceTimeline .

UserTiming ma pojęcia znaków (znaczników czasu) i miar (czasów trwania). Możesz zdefiniować dowolną ich liczbę, a będą one widoczne w PerformanceTimeline .

Aby zapisać znacznik czasu, dzwonisz mark(startMarkName). Aby uzyskać czas od pierwszego znaku, wystarczy zadzwonić measure(measurename, startMarkname). Czas trwania jest następnie zapisywany w PerformanceTimeline obok twoich ocen.

function a() {
  window.performance.mark("start");
  ... do stuff ...
  window.performance.measure("myfunctionduration", "start");
}

// duration is window.performance.getEntriesByName("myfunctionduration", "measure")[0];

Funkcja UserTiming jest dostępna w IE10 + i Chrome25 +. Dostępna jest również polifill (którą napisałem).


1
Znakomita i najbardziej aktualna odpowiedź IMHO :) Byłoby jeszcze lepiej przy odrobinie edycji. Powiedziałbym, że moment użytkownik nie jest „jedna opcja” do pomiaru, ale preferowaną opcją, gdy benchmarking nie jest wykonywana na maszynie rozwoju samego. Z polifillem działa on we wszystkich przeglądarkach. I ukrywanie dala szczegóły i kotła z i jest przyczyną tego, że istnieje. performance.nowDate
hashchange

34

Aby uzyskać dokładne wartości, należy użyć interfejsu Performance . Jest obsługiwany w nowoczesnych wersjach Firefox, Chrome, Opera i IE. Oto przykład, w jaki sposób można go użyć:

var performance = window.performance;
var t0 = performance.now();
doWork();
var t1 = performance.now();
console.log("Call to doWork took " + (t1 - t0) + " milliseconds.")

Date.getTime()lub console.time()nie są dobre do pomiaru dokładnego czasu wykonania. Możesz ich użyć, jeśli szybka wstępna ocena jest dla Ciebie odpowiednia. Z grubsza wynika, że ​​można uzyskać przesunięcie o 15–60 ms w czasie rzeczywistym.

Sprawdź ten genialny post na temat pomiaru czasu wykonania w JavaScript. Autor podaje również kilka linków na temat dokładności czasu JavaScript, które warto przeczytać.


Bardzo dobra odpowiedź! To mi bardzo pomogło!
Połącz

18

Użyj Firebug, włącz konsolę i Javascript. Kliknij Profil. Przeładować. Kliknij ponownie Profil. Zobacz raport.


8
Dobra rada, ale oczywiście działa tylko dla FF. Często chcemy porównać prędkości przeglądarki ... :-)
PhiLho

3
W nowym Firebuq ukrywają te opcje w menu, używają CTRL + SHIFT + P lub console.profile (); console..profileEnd ()
user956584

4
Chrome obsługuje console.time()i console.timeEnd()teraz.
julien_c

12
var StopWatch = function (performance) {
    this.startTime = 0;
    this.stopTime = 0;
    this.running = false;
    this.performance = performance === false ? false : !!window.performance;
};

StopWatch.prototype.currentTime = function () {
    return this.performance ? window.performance.now() : new Date().getTime();
};

StopWatch.prototype.start = function () {
    this.startTime = this.currentTime();
    this.running = true;
};

StopWatch.prototype.stop = function () {
    this.stopTime = this.currentTime();
    this.running = false;
};

StopWatch.prototype.getElapsedMilliseconds = function () {
    if (this.running) {
        this.stopTime = this.currentTime();
    }

    return this.stopTime - this.startTime;
};

StopWatch.prototype.getElapsedSeconds = function () {
    return this.getElapsedMilliseconds() / 1000;
};

StopWatch.prototype.printElapsed = function (name) {
    var currentName = name || 'Elapsed:';

    console.log(currentName, '[' + this.getElapsedMilliseconds() + 'ms]', '[' + this.getElapsedSeconds() + 's]');
};

Reper

var stopwatch = new StopWatch();
stopwatch.start();

for (var index = 0; index < 100; index++) {
    stopwatch.printElapsed('Instance[' + index + ']');
}

stopwatch.stop();

stopwatch.printElapsed();

Wynik

Instance[0] [0ms] [0s]
Instance[1] [2.999999967869371ms] [0.002999999967869371s]
Instance[2] [2.999999967869371ms] [0.002999999967869371s]
/* ... */
Instance[99] [10.999999998603016ms] [0.010999999998603016s]
Elapsed: [10.999999998603016ms] [0.010999999998603016s]

performance.now () jest opcjonalny - po prostu przekaż false do funkcji konstruktora StopWatch.


12

Process.hrtime () jest dostępny w Node.js - zwraca wartość w nanosekundach

var hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)

1
jeśli wolisz przekonwertować go na ms e-3 zamiast sugerowanej mikrosekundy e-6: hrtime[0] * 1000 + hrtime[1] / 1000000-> tak, ja też wolę użyć var hrtime! : P
cregox

11

możesz użyć operatora dodawania również tutaj

 var start = +new Date();
 callYourFunctionHere();
 var end = +new Date();
 var time = end - start;
 console.log('total execution time = '+ time + 'ms');

8

Aby rozszerzyć kod vsync, aby mieć możliwość zwrócenia timeEnd jako wartości w NodeJS, użyj tego małego fragmentu kodu.

console.timeEndValue = function(label) { // Add console.timeEndValue, to add a return value
   var time = this._times[label];
   if (!time) {
     throw new Error('No such label: ' + label);
   }
   var duration = Date.now() - time;
   return duration;
};

Teraz użyj kodu w następujący sposób:

console.time('someFunction timer');

someFunction();

var executionTime = console.timeEndValue('someFunction timer');
console.log("The execution time is " + executionTime);


Daje to więcej możliwości. Możesz zapisać czas wykonania, aby wykorzystać go do innych celów, takich jak użycie go w równaniach lub w bazie danych, wysłany do zdalnego klienta przez gniazda sieciowe, obsługiwany na stronie internetowej itp.


8

Możliwe jest użycie tylko jednej zmiennej:

var timer = -performance.now();

// Do something

timer += performance.now();
console.log("Time: " + (timer/1000).toFixed(5) + " sec.")

timer/1000 - konwertować milisekundy na sekundy

.toFixed(5) - przycinać dodatkowe cyfry


5

Ponieważ console.timei performance.nownie są obsługiwane w niektórych głównych przeglądarkach (np. IE10), stworzyłem cienkie narzędzie, które wykorzystuje najlepsze dostępne metody. Brakuje jednak obsługi błędów w przypadku fałszywych zastosowań (wywoływanie End()nie zainicjowanego timera).

Użyj go i ulepsz go, jak chcesz.

Performance: {
    Timer: {},
    Start: function (name) {
        if (console && console.time) {
            console.time(name);
        } else if (window.performance.now) {
            this.Timer[name] = window.performance.now();
        } else {
            this.Timer[name] = new Date().getTime();
        }
    },
    End: function (name) {
        if (console && console.time) {
            console.timeEnd(name);
        } else {
            var result;
            if (window.performance.now) {
                result = window.performance.now() - this.Timer[name];
            } else {
                result = new Date().getTime() - this.Timer[name];
            }
            console.log(name + ": " + result);
        }
    }
}

5

To może ci pomóc.

var t0 = date.now(); doSomething(); var t1 = date.now(); console.log("Call to doSomething took approximate" + (t1 - t0)/1000 + " seconds.")


1
Ten fragment kodu może rozwiązać pytanie, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że w przyszłości odpowiadasz na pytanie czytelników, a ci ludzie mogą nie znać przyczyn Twojej sugestii kodu. Staraj się również nie tłoczyć kodu objaśniającymi komentarzami, co zmniejsza czytelność zarówno kodu, jak i objaśnień!
Filnor

5

Oto dekorator dla funkcji pomiaru czasu

let timed = (f) => (...args)=>{
    let start = performance.now();
    let ret = f(...args);
    console.log(`function ${f.name} took ${(performance.now()-start).toFixed(3)}ms`)
    return ret;   
}

Stosowanie:

let test = ()=>{/*does something*/}
test = timed(test)   // turns the function into a timed function in one line
test()               // run your code as normal, logs 'function test took 1001.900ms' 

Jeśli używasz funkcji asynchronicznych, możesz dokonać timedasynchronizacji i dodać awaitprzed f (... args), i to powinno działać dla nich. Staje się to bardziej skomplikowane, jeśli chcesz, aby jeden dekorator obsługiwał zarówno funkcje synchronizacji, jak i asynchronizacji.


Właśnie tego szukałem. Dziękuję Ci!
Andrew Watters

Czy jest jakiś sposób, aby uczynić go uniwersalnym do użycia również z funkcjami asynchronicznymi?
TotalAMD

4

Dzięki, Achim Koellner, nieco poszerzę twoją odpowiedź:

var t0 = process.hrtime();
//Start of code to measure

//End of code
var timeInMilliseconds = process.hrtime(t0)[1]/1000000; // dividing by 1000000 gives milliseconds from nanoseconds

Pamiętaj, że nie powinieneś robić nic poza tym, co chcesz zmierzyć (na przykład console.log wykonanie będzie miało czas i wpłynie na testy wydajności).

Należy zauważyć, że aby zmierzyć czas wykonania funkcji asynchronicznych, należy wstawić var timeInMilliseconds = process.hrtime(t0)[1]/1000000;wewnątrz wywołania zwrotnego. Na przykład,

var t0 = process.hrtime();
someAsyncFunction(function(err, results) {
var timeInMilliseconds = process.hrtime(t0)[1]/1000000;

});

3

Kilka miesięcy temu stworzyłem własną procedurę, która mierzy funkcję przy użyciu Date.now () - mimo że w tamtym czasie akceptowaną metodą wydawała się performance.now () - ponieważ obiekt wydajności nie jest jeszcze dostępny (zbudowany -in) w stabilnej wersji Node.js.

Dzisiaj robiłem więcej badań i znalazłem inną metodę pomiaru czasu. Ponieważ znalazłem również sposób korzystania z tego w kodzie Node.js, pomyślałem, że podzielę się nim tutaj.

Poniższe przykłady połączono z przykładami podanymi przez w3c i Node.js :

function functionTimer() {
    performance.mark('start')
    functionToBeTimed()
    performance.mark('end')
    performance.measure('Start to End', 'start', 'end')
    const measure = performance.getEntriesByName('Start to End')[0]
    console.log(measure.duration)
}

UWAGA:

Jeśli zamierzasz używać performanceobiektu w aplikacji Node.js, musisz uwzględnić następujące wymagania: const { performance } = require('perf_hooks')


Myślę, że nie potrzebujesz performance.mark('end')w tym przypadku
kofifus

2

istnieje wiele sposobów osiągnięcia tego celu:

  1. using console.time

    console.time('function');
    //run the function in between these two lines for that you need to 
    //measure time taken by the function. ("ex. function();")
    console.timeEnd('function');
  2. jest to najbardziej efektywny sposób: użycie performance.now () , np

    var v1 = performance.now();
    //run the function here for which you have top measure the time 
    var v2 = performance.now();
    console.log("total time  taken = "+(v2-v1)+"milliseconds");
  3. użyj + (dodaj operator) lub getTime ()

    var h2 = +new Date(); //or
    var h2 = new Date().getTime();
    for(i=0;i<500;i++) { /* do something */}
    var h3 = +new Date();   //or 
    var h3 = new Date().getTime();
    var timeTaken = h3-h2;
    console.log("time ====", timeTaken);

Oto, co się stanie, gdy zastosujesz jednoargumentowy operator plus do instancji Date: Uzyskaj wartość danej instancji Date Konwertuj ją na liczbę

UWAGA: getTime()daje lepszą wydajność niż operator jednoargumentowy.


1
export default class Singleton {

  static myInstance: Singleton = null;

  _timers: any = {};

  /**
   * @returns {Singleton}
   */
  static getInstance() {
    if (Singleton.myInstance == null) {
      Singleton.myInstance = new Singleton();
    }

    return this.myInstance;
  }

  initTime(label: string) {
    this._timers[label] = Date.now();
    return this._timers[label];
  }

  endTime(label: string) {
    const endTime = Date.now();
    if (this._timers[label]) {
      const delta = endTime - this._timers[label];
      const finalTime = `${label}: ${delta}ms`;
      delete this._timers[label];
      return finalTime;
    } else {
      return null;
    }
  }
}

InitTime związane z string.

return Singleton.getInstance().initTime(label); // Returns the time init

return Singleton.getInstance().endTime(label); // Returns the total time between init and end


1

Jeśli chcesz zmierzyć czas między wieloma zagnieżdżonymi rzeczami, możesz użyć tego:

function timer(lap){ 
    if(lap) console.log(`${lap} in: ${(performance.now()-timer.prev).toFixed(3)}ms`); 
    timer.prev = performance.now();
}

Podobne do console.time (), ale łatwiejsze w użyciu, jeśli nie musisz śledzić poprzednich timerów.

Jeśli podoba ci się niebieski kolor z console.time (), możesz zamiast tego użyć tej linii

console.log(`${lap} in: %c${(performance.now()-timer.prev).toFixed(3)}ms`, 'color:blue');

// Usage: 
timer()              // set the start
// do something 
timer('built')       // logs 'built in: 591.815ms'
// do something
timer('copied')      // logs 'copied in: 0.065ms'
// do something
timer('compared')    // logs 'compared in: 36.41ms'

1

W moim przypadku korzystam z @ gramatyki suger i kompiluję go z babelem.
Problemem tej metody jest to, że funkcja musi znajdować się wewnątrz obiektu.

Przykładowy kod JS

function timer() {
    return (target, propertyKey, descriptor) => {
        const start = Date.now();
        let oldFunc = descriptor.value;

        descriptor.value = async function (){
            var result = await oldFunc.apply(this, arguments);
            console.log(Date.now() - start);
            return result;
        }
    }
}

// Util function 
function delay(timeout) {
    return new Promise((resolve) => setTimeout(() => {
        resolve();
    }, timeout));
}

class Test {
    @timer()
    async test(timout) {
        await delay(timout)
        console.log("delay 1");
        await delay(timout)
        console.log("delay 2");
    }
}

const t = new Test();
t.test(1000)
t.test(100)

.babelrc (dla babel 6)

 {
    "plugins": [
        "transform-decorators-legacy"
    ]
 }

1

Stoper z łącznymi cyklami

Współpracuje z serwerem i klientem (Node lub DOM), używa Performance interfejsu API. Dobrze, gdy masz wiele małych cykli, np. W funkcji o nazwie 1000 razy, która przetwarza 1000 obiektów danych, ale chcesz zobaczyć, jak każda operacja w tej funkcji stanowi sumę.

Tak więc ten wykorzystuje moduł globalnego timera (singleton). Taki sam jak wzorzec singletonu klasy, nieco prostszy w użyciu, ale musisz umieścić go w osobnym stopwatch.jspliku np .

const perf = typeof performance !== "undefined" ? performance : require('perf_hooks').performance;
const DIGITS = 2;

let _timers = {};

const _log = (label, delta?) => {
    if (_timers[label]) {
        console.log(`${label}: ` + (delta ? `${delta.toFixed(DIGITS)} ms last, ` : '') +
            `${_timers[label].total.toFixed(DIGITS)} ms total, ${_timers[label].cycles} cycles`);
    }
};

export const Stopwatch = {
    start(label) {
        const now = perf.now();
        if (_timers[label]) {
            if (!_timers[label].started) {
                _timers[label].started = now;
            }
        } else {
            _timers[label] = {
                started: now,
                total: 0,
                cycles: 0
            };
        }
    },
    /** Returns total elapsed milliseconds, or null if stopwatch doesn't exist. */
    stop(label, log = false) {
        const now = perf.now();
        if (_timers[label]) {
            let delta;
            if(_timers[label].started) {
                delta = now - _timers[label].started;
                _timers[label].started = null;
                _timers[label].total += delta;
                _timers[label].cycles++;
            }
            log && _log(label, delta);
            return _timers[label].total;
        } else {
            return null;
        }
    },
    /** Logs total time */
    log: _log,
    delete(label) {
        delete _timers[label];
    }
};

1

Najlepszym sposobem byłoby użycie performance hooksmodułu. Chociaż niestabilna, można markkonkretne obszary kodu i między zaznaczonych obszarach.measureduration

const { performance, PerformanceObserver } = require('perf_hooks');

const measures = []

const obs = new PerformanceObserver(list => measures.push(...list.getEntries()));
obs.observe({ entryTypes: ['measure'] });
const getEntriesByType = cb => cb(measures);

const doSomething = val => {
  performance.mark('beginning of the process');

  val *= 2;

  performance.mark('after multiplication');

  performance.measure('time taken', 'beginning of the process', 'after multiplication');

  getEntriesByType(entries => {
    entries.forEach(entry => console.log(entry));
  })

  return val;
}

doSomething(4);

Wypróbuj tutaj


0
const { performance } = require('perf_hooks');

function addUpTo(n) {
  let total = 0;
  for (let i = 1; i <= n; i++) {
    total += i;
  }
  return total;
}


let t1 = performance.now();
addUpTo(1000000000);
let t2 = performance.now();
console.log(`Time elapsed: ${(t2 - t1) / 1000} seconds`);
// Time elapsed: 1.1261566010713577 seconds

0

Z wydajnością

NodeJs: Wymagane jest zaimportowanie klasy wydajności

var time0 = performance.now(); // Store the time at this point into time0

yourFunction();   // The function you're measuring time for 

var time1 = performance.now(); // Store the time at this point into time1

console.log("youFunction took " + (time1 - time0) + " milliseconds to execute");

Korzystanie z console.time

console.time('someFunction');

someFunction(); // Whatever is timed goes between the two "console.time"

console.timeEnd('someFunction');

0
  1. Aby uruchomić stoper, użyjconsole.time("myTimer");
  2. Opcjonalnie: Aby wydrukować upływający czas, użyj console.timeLog("myTimer");
  3. Na koniec, aby zatrzymać stoper i wydrukować czas końcowy:console.timeEnd("myTimer");

Możesz przeczytać więcej na ten temat na MDN oraz w dokumentacji node.js .

Dostępne w Chrome, Firefox, Opera i NodeJS. (nie w Edge ani Internet Explorer).


-2

Jak wspomniano wcześniej, sprawdź i użyj wbudowanego timera. Ale jeśli chcesz lub musisz napisać tutaj, moje dwa centy:

//=-=|Source|=-=//
/**
 * JavaScript Timer Object
 *
 *      var now=timer['elapsed'](); 
 *      timer['stop']();
 *      timer['start']();
 *      timer['reset']();
 * 
 * @expose
 * @method timer
 * @return {number}
 */
timer=function(){
    var a=Date.now();
    b=0;
    return{
        /** @expose */
        elapsed:function(){return b=Date.now()-a},
        start:function(){return a=Date.now()},
        stop:function(){return Date.now()},
        reset:function(){return a=0}
    }
}();

//=-=|Google Advanced Optimized|=-=//
timer=function(){var a=Date.now();b=0;return{a:function(){return b=Date.now()-a},start:function(){return a=Date.now()},stop:function(){return Date.now()},reset:function(){return a=0}}}();

Kompilacja zakończyła się sukcesem!

  • Rozmiar oryginału: 219 bajtów spakowanych gzip (405 bajtów nieskompresowanych)
  • Skompilowany rozmiar: 109 bajtów zgzipowanych (187 bajtów nieskompresowanych)
  • Zaoszczędź 50,23% zniżki na rozmiar gzipa (53,83% bez gzipa)

-6

Przyjęta odpowiedź jest błędna !

Ponieważ JavaScript jest asynchroniczny, wartości końca zmiennej przyjętej odpowiedzi byłyby błędne.

var start = new Date().getTime();

for (i = 0; i < 50000; ++i) {
// JavaScript is not waiting until the for is finished !!
}

var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time); 

Wykonanie for może być bardzo szybkie, więc nie widać, że wynik jest nieprawidłowy. Możesz to przetestować za pomocą kodu wykonującego jakieś żądanie:

var start = new Date().getTime();

for (i = 0; i < 50000; ++i) {
  $.ajax({
    url: 'www.oneOfYourWebsites.com',
    success: function(){
       console.log("success");
    }
  });
}

var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time); 

Tak więc alert wyświetli się bardzo szybko, ale w konsoli zobaczysz, że żądania ajax są kontynuowane.

Oto, jak powinieneś to zrobić: https://developer.mozilla.org/en-US/docs/Web/API/Performance.now


9
Nie dzieje się tak z powodu pętli for. Pętla for będzie czekać do ostatniej pętli, aż przejdzie do kodu źródłowego. Połączenia AJAX są asynchroniczne. Są też inne funkcje, które działają asynchronicznie. Ale pętla for nie jest asynchronicznym plikiem wykonywalnym.
Scriptlabs,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.