วิธีการวัดเวลาที่ฟังก์ชั่นดำเนินการ


1192

ฉันต้องใช้เวลาดำเนินการเป็นมิลลิวินาที

เดิมฉันถามคำถามนี้กลับในปี 2008 คำตอบที่ยอมรับแล้วคือการใช้ Date ใหม่ (). getTime ()อย่างไรก็ตามเราทุกคนสามารถตกลงกันได้แล้วว่าการใช้Performance.now () API นั้นเหมาะสมกว่า ดังนั้นฉันจึงเปลี่ยนคำตอบที่ยอมรับให้กับคำตอบนี้


3
บ่อยครั้งที่ข้อความเกี่ยวกับสิ่งที่คุณพยายามทำให้สำเร็จด้วยเวลาดำเนินการสามารถพิสูจน์ได้ว่ามีประโยชน์มากกว่าการตอบคำถามเพียงอย่างเดียว ทุกวันนี้การใช้ Profiling ใน Firebug หรือเครื่องมือ Chrome Dev มักเป็นวิธีที่ดีกว่าในการค้นหารหัสที่ดูดน้ำซีพียูของคุณ
oligofren

นี่คือวิธีที่คุณสามารถทำได้ในแบบคลาสสิกDateซึ่งให้คุณmsและเพียงพอสำหรับกรณีส่วนใหญ่ฉันคิดว่าalbertech.blogspot.com/2015/07/ ...... ... แต่ใช่คุณควรดูจริง ๆPerformance.now
jar

5
performance.now()ไม่ทำงานในโหนด new Date().getTime()จะทำงานในโหนด
Ryan Walker

1
หมายเลข 1,000 upvote woop woop: D
Kiksen

1
@oligofren - บางครั้งคุณอาจต้องการเก็บข้อมูลนี้ ฉันมีสถานการณ์ที่ฉันเขียนสิ่งนี้เพื่อจัดทำดัชนี DB
ThomasRones

คำตอบ:


1758

การใช้ 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: จำเป็นต้องนำเข้าperformanceคลาส


ใช้console.time :(ที่ไม่ได้มาตรฐาน)( มาตรฐานการดำรงชีวิต )

console.time('someFunction')

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

console.timeEnd('someFunction')

หมายเหตุ :
สตริงที่ส่งผ่านไปยังtime()และtimeEnd()เมธอดต้องตรงกัน
(เพื่อให้ตัวจับเวลาเสร็จสิ้นตามที่คาดไว้)

console.time() เอกสาร:

  1. เอกสารเกี่ยวกับ NodeJS
  2. เอกสาร MDN (ฝั่งไคลเอ็นต์)

27
ได้รับการสนับสนุนโดยเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของ Chrome เช่นกัน
julien_c

3
นี่เป็นวิธีที่ดีที่สุดในการรวบรวมเวลาที่ถูกต้องจากสิ่งที่ฉันเข้าใจ
Ash Blue

6
คุณไม่จำเป็นต้องใช้ฟังก์ชั่นระหว่างสองคำสั่งเหรอ? ตอนนี้คุณวัดเวลาที่ใช้ในการกำหนดไม่ใช่เพื่อดำเนินการ ถูกต้องฉันหากฉันผิด ...
Cristian

2
ลิงก์ไปยังบทความ MDN เกี่ยวกับคุณลักษณะนี้: developer.mozilla.org/en-US/docs/DOM/console.time
nullability

6
ใช่คุณสามารถทำได้ `totalTime + = console.timeEnd ('timer') 'และทำเพื่อตัวจับเวลาแต่ละตัว
vsync

637

ใช้Date ใหม่ (). getTime ()

เมธอด getTime () ส่งคืนจำนวนมิลลิวินาทีตั้งแต่เที่ยงคืนของวันที่ 1 มกราคม 1970

อดีต

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
โปรดทราบว่าคุณสามารถแทนที่ + new Date () สำหรับการโทร getTime (): var start = + new Date (); // ทำสิ่งเตือน ("เวลาดำเนินการ:" + (+ ใหม่วันที่ ()) - เริ่มต้น);
J c

55
การกำหนดเวลาไม่ถูกต้องเนื่องจากวันที่ไม่ได้มีไว้สำหรับฟังก์ชั่นนี้ ฉันจะกล้าที่นี่และบอกว่าคุณควรใช้ตัวอย่างของ vsync หากคุณต้องการเวลาที่แม่นยำ แม้ว่ามันจะใช้ได้เฉพาะใน Chrome และ Firefox ATM
Ash Blue

9
ระวัง getMilliseconds () จะให้เศษเสี้ยวเป็นมิลลิวินาทีของวินาทีปัจจุบัน หากคุณแทนที่ getTime () ด้วย getMilliseconds () คุณสามารถรับผลลัพธ์เชิงลบได้หากคุณข้ามวินาที
RickyA

6
คำตอบโดย vsync นั้นถูกต้องมากขึ้นตามมาตรฐานของวันนี้และการใช้ Date () อาจส่งผลให้เกิดผลลัพธ์ที่ผิดพลาดอย่างมากโดยเฉพาะอย่างยิ่งบนแพลตฟอร์ม Windows ที่ผลลัพธ์อาจถูกปัดเศษ + พื้นไปจนถึงขอบเขต 15ms ใกล้เคียง การกำหนดเวลา 0ms บนบิตโค้ดขนาดเล็ก
oligofren

29
@AshBlue window.performance.nowเราควรจะใช้ ดูstackoverflow.com/a/15641427/632951
Pacerier

405

อย่าใช้วันที่ () อ่านด้านล่าง.

ใช้performance.now() :

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

มันทำงานบน:

  • IE 10 ++

  • FireFox 15 ++

  • Chrome 24 ++

  • Safari 8 ++

  • Opera 15 ++

  • Android 4.4 ++

  • ฯลฯ

console.timeอาจทำงานได้สำหรับคุณแต่ไม่ใช่มาตรฐาน§ :

คุณสมบัตินี้ไม่ได้มาตรฐานและไม่ได้อยู่ในมาตรฐาน ห้ามใช้กับไซต์ที่ผลิตซึ่งหันหน้าไปทางเว็บ: มันจะไม่ทำงานสำหรับผู้ใช้ทุกคน มีก็อาจจะเข้ากันไม่ได้ขนาดใหญ่ระหว่างการใช้งานและพฤติกรรมที่อาจมีการเปลี่ยนแปลงในอนาคต

นอกจากนี้ยังสนับสนุนเบราว์เซอร์performance.nowที่ดูเหมือนว่าจะมีศักยภาพconsole.timeที่จะให้การกำหนดเวลาที่ถูกต้องมากขึ้นในขณะที่มันดูเหมือนจะเป็นรุ่นเปลือยกระดูกของ


<rant> นอกจากนี้อย่าใช้Dateเพื่ออะไรเพราะมันได้รับผลกระทบจากการเปลี่ยนแปลงใน "เวลาของระบบ" ซึ่งหมายความว่าเราจะได้รับผลลัพธ์ที่ไม่ถูกต้องเช่น "เวลาลบ" - เมื่อผู้ใช้ไม่มีเวลาระบบที่แม่นยำ

ในเดือนตุลาคม 2014 นาฬิการะบบของฉันไปยุ่งเหยิงและเดาว่า .... ฉันเปิด Gmail และเห็นอีเมลของวันทั้งหมดของฉัน "ส่ง0 นาทีที่ผ่านมา " และฉันคิดว่า Gmail ควรถูกสร้างขึ้นโดยวิศวกรระดับโลกจาก Google .......

(ตั้งนาฬิการะบบของคุณเป็นหนึ่งปีที่ผ่านมาและไปที่ Gmail เพื่อให้เราทุกคนสามารถหัวเราะได้บางทีวันหนึ่งเราจะมีHall of Shameสำหรับ JS Date)

now()ฟังก์ชั่นของ Google Spreadsheet ก็ประสบปัญหานี้เช่นกัน

เวลาเดียวที่คุณจะใช้Dateคือเมื่อคุณต้องการแสดงเวลานาฬิการะบบของผู้ใช้ให้กับผู้ใช้ ไม่ได้เมื่อคุณต้องการที่จะได้รับเวลาหรือวัดอะไร


3
สิ่งที่ฉันกำลังมองหา! ฉันต้องการที่จะเพิ่มหลายครั้งด้วยกันไม่สามารถทำได้ด้วยเวลาคอนโซล
เรย์

8
โปรดทราบว่านี่ยังไม่ได้รับการสนับสนุนในซาฟารี: developer.mozilla.org/en-US/docs/Web/API/Performance.now ()
Akos K

2
ฉันใช้ Firebug Profile และ performance.now () และพวกเขาทำงานได้ดี Performance.now () ยืนยันผลลัพธ์ของฉันจากโปรไฟล์
Vincent Jia

2
ไม่ทำงานใน Hangup ที่ใหญ่ที่สุดของฉันซึ่งก็คือ IE7 (ลูกค้าองค์กร) ฉันไม่สนใจเกี่ยวกับการวัดประสิทธิภาพในโครเมี่ยมมันรวดเร็วเสมอ
Nick

2
นี่เป็นวิธีที่ดีกว่าแล้วใช้ console.time ()
Sanjeev

52

หากคุณต้องการที่จะได้รับเวลาในการประมวลฟังก์ชั่นในเครื่องพัฒนาท้องถิ่นของคุณคุณสามารถใช้เครื่องมือ profiling เบราว์เซอร์ของคุณหรือคำสั่งคอนโซลเช่นและconsole.time()console.timeEnd()

เบราว์เซอร์ที่ทันสมัยทั้งหมดมีตัวสร้างโปรไฟล์ JavaScript ในตัว ผู้สร้างโปรไฟล์เหล่านี้ควรให้การวัดที่แม่นยำที่สุดเนื่องจากคุณไม่จำเป็นต้องแก้ไขโค้ดที่มีอยู่ซึ่งอาจส่งผลต่อเวลาในการทำงานของฟังก์ชัน

หากต้องการโปรไฟล์ JavaScript ของคุณ:

  • ในChromeกดF12และเลือกโปรไฟล์แท็บแล้วเก็บรายละเอียด JavaScript CPU
  • ในFirefoxติดตั้ง / เปิด Firebug และคลิกที่ปุ่ม โปรไฟล์
  • ในIE 9+กดF12คลิกที่ScriptหรือProfiler (ขึ้นอยู่กับรุ่น IE ของคุณ)

อีกทางเลือกหนึ่งในการพัฒนาของเครื่องคุณสามารถเพิ่มเครื่องมือในรหัสของคุณด้วยและconsole.time() console.timeEnd()ฟังก์ชั่นเหล่านี้ได้รับการสนับสนุนใน Firefox11 + + Chrome2 และ IE11 + รายงานเกี่ยวกับการจับเวลาที่คุณเริ่ม / console.time()หยุดผ่าน time()ใช้ชื่อตัวจับเวลาที่ผู้ใช้กำหนดเป็นอาร์กิวเมนต์timeEnd()แล้วรายงานเวลาดำเนินการนับตั้งแต่ตัวจับเวลาเริ่มต้น:

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

โปรดทราบว่า Firefox เท่านั้นที่ส่งคืนเวลาที่ผ่านไปในการtimeEnd()โทร เบราว์เซอร์อื่น ๆ เพียงรายงานผลลัพธ์ไปยังคอนโซลนักพัฒนาซอฟต์แวร์: ค่าส่งคืนของtimeEnd()ไม่ได้กำหนด

หากคุณต้องการให้เวลาการทำงานของฟังก์ชันเป็นไปอย่างรวดเร็วคุณจะต้องใช้รหัสของคุณ คุณมีสองทางเลือก คุณสามารถบันทึกเวลาเริ่มต้นและสิ้นสุดได้โดยการสอบถามnew Date().getTime():

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

อย่างไรก็ตามDateวัตถุนั้นมีความละเอียดเป็นมิลลิวินาทีเท่านั้นและจะได้รับผลกระทบจากการเปลี่ยนแปลงนาฬิกาของระบบปฏิบัติการ ในเบราว์เซอร์สมัยใหม่มีตัวเลือกที่ดีกว่า

ตัวเลือกที่ดีคือการใช้เวลาความละเอียดสูงwindow.performance.now()อาคา now()ดีกว่าแบบดั้งเดิมDate.getTime()ในสองวิธีที่สำคัญ:

  1. now()เป็นความละเอียดสองเท่าที่มีความละเอียดระดับมิลลิวินาทีย่อยซึ่งแสดงถึงจำนวนมิลลิวินาทีนับตั้งแต่เริ่มต้นการนำทางของหน้าเว็บ มันส่งคืนจำนวนไมโครวินาทีในเศษส่วน (เช่นค่า 1,000.123 คือ 1 วินาทีและ 123 microseconds)

  2. now()เพิ่มขึ้น monotonically นี้เป็นสิ่งสำคัญDate.getTime()ที่สามารถอาจจะกระโดดไปข้างหน้าหรือแม้กระทั่งย้อนกลับในการโทรตามมา โดยเฉพาะถ้าเวลาของระบบปฏิบัติการมีการอัพเดท (เช่นการซิงโครไนซ์นาฬิกาอะตอม) Date.getTime()จะได้รับการอัพเดตด้วย now()รับประกันว่าจะเพิ่มขึ้น monotonically เสมอดังนั้นจึงไม่ได้รับผลกระทบจากเวลาระบบของ OS - มันจะเป็นเวลานาฬิกาแขวนผนังเสมอ (สมมติว่านาฬิกาแขวนของคุณไม่ได้เป็นอะตอม ... )

now()สามารถนำมาใช้ในเกือบทุกสถานที่ที่new Date().getTime(), + new Dateandt Date.now()มี ยกเว้นที่Dateและnow()เวลาที่ไม่ผสมเป็นDateอยู่บนพื้นฐานของยูนิกซ์ยุค (จำนวนมิลลิวินาทีตั้งแต่ปี 1970) ในขณะที่now()เป็นจำนวนมิลลิวินาทีตั้งแต่การนำทางเพจของคุณเริ่มต้น (จึงจะมีขนาดเล็กกว่าDate)

นี่คือตัวอย่างวิธีการใช้งานnow():

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

now()ได้รับการสนับสนุนใน Chrome เสถียร, Firefox 15+ และ IE10 นอกจากนี้ยังมีpolyfillsหลายแบบให้เลือก

หนึ่งในตัวเลือกอื่น ๆ สำหรับการวัดระยะเวลาการดำเนินการอยู่ในป่าเป็น UserTiming UserTiming พฤติกรรมคล้ายกับconsole.time()และconsole.timeEnd()แต่มันใช้เดียวกันความละเอียดสูงประทับเวลาที่now()ใช้ (เพื่อให้คุณได้รับการย่อยมิลลิวินาที monotonically นาฬิกาที่เพิ่มขึ้น) และบันทึกการประทับเวลาและระยะเวลาที่จะPerformanceTimeline

UserTiming มีแนวคิดของเครื่องหมาย (การประทับเวลา) และการวัด (ระยะเวลา) คุณสามารถกำหนดเป็นจำนวนมากของทั้งสองตามที่คุณต้องการและพวกเขากำลังสัมผัสบนPerformanceTimeline

mark(startMarkName)ในการบันทึกการประทับเวลาที่คุณเรียก measure(measurename, startMarkname)ที่จะได้รับระยะเวลาตั้งแต่เครื่องหมายครั้งแรกของคุณคุณก็เรียก ระยะเวลาจะถูกบันทึกใน PerformanceTimeline ข้างเครื่องหมายของคุณ

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

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

UserTiming มีให้ใน IE10 + และ Chrome25 + นอกจากนี้ยังมีpolyfill (ซึ่งฉันเขียน)


1
คำตอบที่ยอดเยี่ยมและเป็นปัจจุบัน IMHO :) มันจะดียิ่งขึ้นหากมีการแก้ไขเล็กน้อย ผมบอกว่าระยะเวลาที่ผู้ใช้ไม่ได้เป็น "หนึ่งในตัวเลือกอื่น ๆ" สำหรับการวัด แต่ตัวเลือกที่ต้องการเมื่อเปรียบเทียบไม่ได้ทำบนเครื่องการพัฒนาตัวเอง โพลีฟิลของคุณจะทำงานได้กับทุกเบราว์เซอร์ และซ่อนรายละเอียดและแผ่นเกราะของและเป็นเหตุผลที่มีอยู่ performance.nowDate
hashchange

34

เพื่อให้ได้ค่าที่แม่นยำที่คุณควรใช้อินเตอร์เฟซที่ผลการดำเนินงาน ได้รับการสนับสนุนใน Firefox, Chrome, Opera และ IE เวอร์ชันใหม่ นี่คือตัวอย่างของวิธีการใช้:

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

Date.getTime()หรือconsole.time()ไม่ดีสำหรับการวัดเวลาดำเนินการที่แม่นยำ คุณสามารถใช้มันได้หากการประมาณคร่าวๆอย่างรวดเร็วนั้นโอเคสำหรับคุณ โดยประมาณแล้วฉันหมายถึงคุณสามารถเปลี่ยน 15-60 ms จากเวลาจริง

ตรวจสอบโพสต์ที่ยอดเยี่ยมนี้เกี่ยวกับการวัดเวลาดำเนินการใน JavaScript ผู้เขียนยังให้ลิงค์สองสามข้อเกี่ยวกับความถูกต้องของเวลา JavaScript, มูลค่าการอ่าน


คำตอบที่ดีมาก! สิ่งนี้ช่วยฉันได้มาก!
รวม

18

ใช้ Firebug เปิดใช้งานทั้งคอนโซลและ Javascript คลิกโปรไฟล์ โหลด คลิกโปรไฟล์อีกครั้ง ดูรายงาน


8
คำแนะนำที่ดี แต่เห็นได้ชัดว่าใช้ได้กับ FF เท่านั้น เรามักจะต้องการเปรียบเทียบความเร็วของเบราว์เซอร์ ... :-)
โคลโฮ

3
ใน Firebuq ใหม่พวกเขาซ่อนตัวเลือกนี้ไปที่เมนูใช้ CTRL + SHIFT + P หรือ console.profile (); console..profileEnd ()
user956584

4
Chrome รองรับconsole.time()และconsole.timeEnd()ตอนนี้ด้วย
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]');
};

เกณฑ์มาตรฐาน

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

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

stopwatch.stop();

stopwatch.printElapsed();

เอาท์พุต

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 ()เป็นทางเลือก - เพียงแค่ส่งค่าเท็จไปยังฟังก์ชันตัวสร้าง StopWatch


12

process.hrtime () สามารถใช้ได้ภายในNode.js - มันจะส่งกลับค่าในหน่วยนาโนวินาที

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

1
ถ้าคุณอยากแปลงเป็น ms e-3 มากกว่า microsecond ที่แนะนำ e-6: hrtime[0] * 1000 + hrtime[1] / 1000000-> ใช่ฉันก็ใช้var hrtimeเช่นกัน! : P
cregox

11

คุณสามารถใช้ตัวดำเนินการเพิ่มได้ที่นี่

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

8

ในการขยายรหัสของ vsync ให้มีความสามารถในการคืนค่า timeEnd เป็นค่าใน NodeJS ให้ใช้โค้ดขนาดเล็กนี้

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;
};

ตอนนี้ใช้รหัสดังนี้:

console.time('someFunction timer');

someFunction();

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


สิ่งนี้ทำให้คุณมีความเป็นไปได้มากขึ้น คุณสามารถจัดเก็บเวลาดำเนินการที่จะใช้เพื่อวัตถุประสงค์เพิ่มเติมเช่นใช้ในสมการหรือเก็บไว้ในฐานข้อมูลส่งไปยังไคลเอนต์ระยะไกลผ่านเว็บกระเป๋าให้บริการบนหน้าเว็บ ฯลฯ


8

สามารถใช้ตัวแปรเดียวเท่านั้น:

var timer = -performance.now();

// Do something

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

timer/1000 - เพื่อแปลงมิลลิวินาทีเป็นวินาที

.toFixed(5) - เพื่อตัดเลขพิเศษ


5

ตั้งแต่console.timeและperformance.nowไม่ได้รับการสนับสนุนในเบราว์เซอร์หลักบางตัว (เช่น IE10) ฉันจึงสร้างยูทิลิตีที่บางซึ่งใช้วิธีการที่ดีที่สุด อย่างไรก็ตามมันไม่มีข้อผิดพลาดในการจัดการกับการใช้งานที่ผิดพลาด (การเรียกEnd()ใช้ตัวจับเวลาที่ไม่ได้กำหนดค่าเริ่มต้น)

ใช้มันและปรับปรุงตามที่คุณต้องการ

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

มันอาจช่วยคุณได้

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


1
ในขณะที่ข้อมูลโค้ดนี้อาจแก้ไขคำถามรวมถึงคำอธิบายช่วยปรับปรุงคุณภาพของโพสต์ของคุณ จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตและคนเหล่านั้นอาจไม่ทราบสาเหตุของการแนะนำรหัสของคุณ โปรดอย่าพยายามทำให้รหัสของคุณแน่นเกินไปด้วยคำอธิบายที่อธิบายซึ่งจะช่วยลดความสามารถในการอ่านของทั้งรหัสและคำอธิบาย!
Filnor

5

นี่คือมัณฑนากรสำหรับฟังก์ชั่นจับเวลา

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;   
}

การใช้งาน:

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' 

หากคุณใช้ฟังก์ชั่น async คุณสามารถสร้างtimedasync และเพิ่มawaitก่อนหน้า f (... args) และนั่นควรจะใช้ได้สำหรับสิ่งเหล่านั้น มันจะซับซ้อนมากขึ้นหากคุณต้องการให้มัณฑนากรรายหนึ่งจัดการกับทั้งฟังก์ชั่นซิงค์และ async


นี่คือสิ่งที่ฉันกำลังมองหา ขอบคุณ!
Andrew Watters

มีวิธีใดที่จะทำให้เป็นสากลที่จะใช้กับฟังก์ชั่น async ด้วยหรือไม่?
TotalAMD

4

ขอบคุณ Achim Koellner จะขยายคำตอบของคุณอีกเล็กน้อย:

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

โปรดทราบว่าคุณไม่ควรทำอะไรนอกเหนือจากสิ่งที่คุณต้องการวัด (ตัวอย่างเช่น console.logจะใช้เวลาในการดำเนินการและจะส่งผลต่อการทดสอบประสิทธิภาพด้วย)

โปรดทราบว่าตามลำดับโดยการวัดเวลาดำเนินการฟังก์ชันอะซิงโครนัสคุณควรแทรกvar timeInMilliseconds = process.hrtime(t0)[1]/1000000;ภายในการเรียกกลับ ตัวอย่างเช่น,

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

});

3

สองสามเดือนที่ผ่านมาฉันรวบรวมกิจวัตรของตัวเองที่ใช้งานฟังก์ชั่นโดยใช้ Date.now () - แม้ว่าในเวลานั้นวิธีการที่ได้รับการยอมรับดูเหมือนว่าจะเป็น performance.now () - เพราะวัตถุประสิทธิภาพยังไม่พร้อมใช้งาน -in) ในการปล่อย Node เสถียร

วันนี้ฉันกำลังค้นคว้าเพิ่มเติมและพบวิธีการอื่นในการกำหนดเวลา ตั้งแต่ฉันพบวิธีใช้สิ่งนี้ในรหัส Node.js ฉันคิดว่าฉันจะแบ่งปันที่นี่

ข้อมูลต่อไปนี้รวมจากตัวอย่างที่กำหนดโดยw3cและ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)
}

บันทึก:

หากคุณตั้งใจจะใช้performanceวัตถุในแอป Node.js คุณต้องรวมข้อกำหนดดังต่อไปนี้: const { performance } = require('perf_hooks')


ฉันคิดว่าคุณไม่ต้องการperformance.mark('end')ในกรณีนี้
kofifus

3

มีหลายวิธีในการบรรลุวัตถุประสงค์นี้:

  1. ใช้ 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. นี่เป็นวิธีที่มีประสิทธิภาพที่สุด: การ ใช้ performance.now ()เช่น

    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. ใช้ + (เพิ่มตัวดำเนินการ) หรือ 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);

นี่คือสิ่งที่เกิดขึ้นเมื่อคุณใช้ตัวดำเนินการ unary plus กับอินสแตนซ์ Date: รับค่าของอินสแตนซ์ Date ที่เป็นปัญหาแปลงเป็นตัวเลข

หมายเหตุ: getTime()ให้ประสิทธิภาพที่ดีกว่าตัวดำเนินการ unary +


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 stringที่เกี่ยวข้องกับ

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

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


1

หากคุณต้องการวัดเวลาระหว่างสิ่งต่าง ๆ ที่ไม่ซ้อนกันคุณสามารถใช้สิ่งนี้:

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

คล้ายกับ console.time () แต่ใช้งานง่ายขึ้นหากคุณไม่จำเป็นต้องติดตามตัวจับเวลาก่อนหน้า

ถ้าคุณชอบสีฟ้าจาก console.time () คุณสามารถใช้บรรทัดนี้แทน

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

ในกรณีของฉันฉันชอบใช้ @ grammar suger และคอมไพล์ด้วย babel
ปัญหาของวิธีนี้คือฟังก์ชั่นนั้นจะต้องอยู่ภายในวัตถุ

ตัวอย่างรหัส 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 (สำหรับ babel 6)

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

1

นาฬิกาจับเวลาพร้อมวงจรสะสม

ทำงานกับเซิร์ฟเวอร์และไคลเอนต์ (Node หรือ DOM) ใช้ Performance API ดีเมื่อคุณมีวัฏจักรเล็ก ๆ มากมายเช่นในฟังก์ชั่นที่เรียกว่า 1,000 เท่าที่ประมวลผลออบเจ็กต์ข้อมูล 1,000 ชิ้น แต่คุณต้องการดูว่าแต่ละการดำเนินการในฟังก์ชั่นนี้รวมกันเป็นเท่าใด

ดังนั้นอันนี้ใช้ตัวจับเวลาโมดูลโกลบอล (ซิงเกิล) เหมือนกับรูปแบบคลาสซิงเกิลเพียงใช้ง่ายขึ้นเล็กน้อย แต่คุณต้องใส่ในstopwatch.jsไฟล์แยกต่างหากเช่น

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

วิธีที่ดีที่สุดคือการใช้performance hooksโมดูล แม้ว่าจะไม่แน่นอนคุณสามารถmarkพื้นที่เฉพาะของรหัสของคุณและพื้นที่ระหว่างการทำเครื่องหมาย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);

ลองที่นี่


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

ด้วยประสิทธิภาพ

NodeJs: จำเป็นต้องนำเข้าคลาสประสิทธิภาพ

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");

ใช้ console.time

console.time('someFunction');

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

console.timeEnd('someFunction');

0
  1. เพื่อเริ่มจับเวลาใช้console.time("myTimer");
  2. ทางเลือก:หากต้องการพิมพ์เวลาที่ผ่านไปให้ใช้ console.timeLog("myTimer");
  3. ในที่สุดเมื่อต้องการหยุดตัวจับเวลาและพิมพ์ครั้งสุดท้าย:console.timeEnd("myTimer");

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้เมื่อวันที่MDNและในเอกสาร Node.js

พร้อมใช้งานบน Chrome, Firefox, Opera และ NodeJS (ไม่ใช่ใน Edge หรือ Internet Explorer)


-2

ตามที่ระบุไว้ก่อนหน้านี้ตรวจสอบและใช้ในตัวจับเวลา แต่ถ้าคุณต้องการหรือจำเป็นต้องเขียนของคุณเองที่นี่เป็นสองเซ็นต์ของฉัน:

//=-=|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}}}();

การรวบรวมเป็นความสำเร็จ!

  • ขนาดดั้งเดิม: 219 ไบต์ gzipped (ไม่บีบอัด 405 ไบต์)
  • ขนาดคอมไพล์: 109 ไบต์ gzipped (ไม่มีการบีบอัด 187 ไบต์)
  • บันทึก 50.23% จากขนาด gzipped (53.83% โดยไม่มี gzip

-6

คำตอบที่ยอมรับนั้นผิด !

เนื่องจาก JavaScript เป็นแบบอะซิงโครนัสค่าของจุดสิ้นสุดตัวแปรของคำตอบที่ยอมรับจะผิด

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); 

การดำเนินการของ for อาจเร็วมากดังนั้นคุณจะไม่เห็นว่าผลลัพธ์นั้นผิด คุณสามารถทดสอบด้วยรหัสที่ทำตามคำขอ:

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); 

ดังนั้นการแจ้งเตือนจะแจ้งให้ทราบอย่างรวดเร็ว แต่ในคอนโซลคุณจะเห็นว่าคำขอ ajax ดำเนินการต่อ

นี่คือวิธีที่คุณควรทำ: https://developer.mozilla.org/en-US/docs/Web/API/Performance.now


9
ไม่ใช่เพราะ for for loop การวนรอบจะรอจนกว่าการวนซ้ำครั้งล่าสุดจนกว่ามันจะลงบนซอร์สโค้ดของคุณ การโทร AJAX เป็นแบบซิงค์ และยังมีฟังก์ชั่นอื่น ๆ ที่เรียกใช้ async แต่ for for loop ไม่ได้เรียกใช้ async
Scriptlabs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.