การวัดเวลาการทำงานของเมธอด (Method Execution Time) เป็นสิ่งสำคัญสำหรับ Performance Tuning และ Profiling
วิธีการวัดที่นิยมใช้
- System.currentTimeMillis() - มิลลิวินาที
- System.nanoTime() - นาโนวินาที (แม่นยำกว่า)
- Instant.now() + Duration.between() - Java 8 Time API (แนะนำ)
- Apache Commons StopWatch - ไลบรารีเสริม สะดวกใช้งาน
ตัวอย่างเปรียบเทียบ 4 วิธีในโปรแกรมเดียว
import java.time.Duration;
import java.time.Instant;
import org.apache.commons.lang3.time.StopWatch;
public class Example {
public void test() {
int num = 0;
for (int i = 0; i <= 50; i++) {
num = num + i;
System.out.print(num + ", ");
}
}
public static void main(String args[]) {
Example obj = new Example();
// 1. nanoTime()
long start1 = System.nanoTime();
obj.test();
long end1 = System.nanoTime();
System.out.println("Elapsed Time in nano seconds: " + (end1 - start1));
// 2. currentTimeMillis()
long start2 = System.currentTimeMillis();
obj.test();
long end2 = System.currentTimeMillis();
System.out.println("Elapsed Time in milli seconds: " + (end2 - start2));
// 3. Instant + Duration
Instant inst1 = Instant.now();
obj.test();
Instant inst2 = Instant.now();
System.out.println("Elapsed Time: " + Duration.between(inst1, inst2));
// 4. StopWatch
StopWatch stopWatch = new StopWatch();
stopWatch.start();
obj.test();
stopWatch.stop();
System.out.println("Elapsed Time in milliseconds: " + stopWatch.getTime());
}
}
ผลลัพธ์ตัวอย่าง
Elapsed Time in nano seconds: 1882300 Elapsed Time in milli seconds: 1 Elapsed Time: PT0.001S Elapsed Time in milliseconds: 1
การอธิบายผลลัพธ์
- nanoTime: แสดงค่าในนาโนวินาที (1,882,300 ns ≈ 1.88 ms)
- currentTimeMillis: แสดง 1 ms (ปัดเศษ)
- Duration: แสดงในรูปแบบ ISO-8601 (PT0.001S = 0.001 วินาที)
- StopWatch: แสดง 1 ms
ข้อสังเกตสำคัญ
- การรันครั้งแรกมักช้ากว่าเพราะ JIT Compilation และ Class Loading
- ควร Warm up โดยรันเมธอดหลายครั้งก่อนวัดจริง
- สำหรับ Benchmarking จริง ควรใช้ JMH (Java Microbenchmark Harness)
- StopWatch.getTime() คืนค่าเป็นมิลลิวินาที ไม่ใช่นาที (ชื่อเมธอดสับสน)
แนวทางปฏิบัติที่ดี (Best Practice)
// แนวทางสำหรับการวัดที่แม่นยำกว่า
public static long measureExecutionTime(Runnable task) {
// Warm up
for (int i = 0; i < 1000; i++) task.run();
// Actual measurement
long start = System.nanoTime();
for (int i = 0; i < 10000; i++) task.run();
long end = System.nanoTime();
return (end - start) / 10000; // ค่าเฉลี่ยต่อการเรียก (nanoseconds)
}