Bạn cần ghi lúc một tác vụ bắt đầu và tác vụ mất bao lâu. Hai câu hỏi nghe gần nhau nhưng nên dùng hai loại dữ liệu khác nhau: thời điểm theo lịch để đối chiếu log, và khoảng thời gian trôi qua để đo duration. Dùng một giá trị cho cả hai dễ dẫn tới phép đo bị ảnh hưởng khi đồng hồ hệ thống được chỉnh.
Bài đối chiếu API ngày 30/10/2026, chạy ví dụ trên Node.js 24.18.1. Không có benchmark so tốc độ hai hàm, không cố tình chỉnh giờ máy. Các số mô phỏng bên dưới chỉ minh họa ý nghĩa phép trừ, không phải sự cố thời gian thực đã quan sát.
Hai mốc gốc khác nhau
Date.now() trả mili giây từ Unix epoch. Nó phù hợp khi cần một timestamp có thể chuyển sang ngày giờ và lưu cùng sự kiện. performance.now() trả số mili giây theo mốc của Performance; trong Node, giá trị 0 tương ứng lúc process bắt đầu.
const {performance} = require('node:perf_hooks');
const wallTimestamp = Date.now();
const processTimestamp = performance.now();
console.log(Number.isInteger(wallTimestamp));
console.log(Number.isFinite(processTimestamp));
Hai dòng in true. Chúng không chứng minh hai giá trị cùng đơn vị gốc hoặc có thể trừ trực tiếp cho nhau. Node 24.18.1 Performance APIs xác nhận mốc process của performance.now; Date.now reference xác nhận mốc epoch.
Dùng duration và timestamp song song
const startedAt = new Date().toISOString();
const start = performance.now();
const result = [3, 1, 2].toSorted((a, b) => a - b);
const durationMs = performance.now() - start;
console.log(startedAt.endsWith('Z'));
console.log(result.join(','));
console.log(Number.isFinite(durationMs), durationMs >= 0);
Kết quả kiểm tra là true, 1,2,3, rồi true true. Bài không công bố con số duration vì thao tác nhỏ này không phải phép thử hiệu năng đại diện. Timestamp ISO mô tả thời điểm bắt đầu theo UTC; duration mô tả đoạn đo trong cùng process.
Đặt ranh giới đo quanh đúng công việc cần quan sát. Thêm console.log vào giữa hai lần đọc đồng hồ sẽ đưa cả công việc ghi log vào duration. Nếu chỉ muốn đo một hàm, ghi log sau khi đã lấy mốc kết thúc.
Khi đồng hồ lịch dịch chuyển
Đồng hồ dùng cho performance được thiết kế đơn điệu, không lùi vì thao tác chỉnh giờ hệ thống. Performance.now reference phân biệt nó với Date.now. Điều đó không có nghĩa mọi môi trường đều bảo đảm độ phân giải vô hạn hoặc cùng hành vi khi máy ngủ.
const simulated = {
wallStart: 10000,
wallEnd: 9000,
monotonicStart: 200,
monotonicEnd: 700,
};
console.log(simulated.wallEnd - simulated.wallStart);
console.log(simulated.monotonicEnd - simulated.monotonicStart);
Đoạn giả lập in -1000 và 500. Nó cho thấy phép trừ hai thời điểm lịch có thể không phản ánh khoảng trôi qua nếu mốc lịch bị dịch chuyển. Đây không phải bằng chứng máy vừa bị chỉnh lùi một giây, cũng không phải phép đo độ trễ mạng.
Tác vụ async cần bao quanh phần được await
async function measuredTask(task) {
const start = performance.now();
const value = await task();
return {value, durationMs: performance.now() - start};
}
measuredTask(() => Promise.resolve('done')).then(({value, durationMs}) => {
console.log(value, durationMs >= 0);
});
Ví dụ in done true. Duration ở đây bao gồm đoạn chờ trong ranh giới await, không phải CPU time riêng của task. Nếu bỏ await và chỉ đo việc tạo Promise, bạn đang đo một công việc khác. Khi muốn ghi cả ca lỗi, thiết kế catch/finally và chính sách log riêng; hàm minh họa vẫn trả rejection khi task thất bại.
So sánh theo tiêu chí sử dụng
| Tiêu chí | Date.now | performance.now |
|---|---|---|
| Dễ bắt đầu | Có sẵn trên Date | Có Performance API; Node dùng perf_hooks |
| Mốc và quyền kiểm soát | Epoch, theo đồng hồ hệ thống | Mốc Performance, phù hợp đo khoảng trong cùng phạm vi |
| Tích hợp | Log, lưu timestamp, chuyển ngày giờ | Instrumentation và duration |
| Hiệu năng | Không benchmark trong bài | Không benchmark trong bài |
| Chi phí duy trì | Cần rõ UTC/timezone khi hiển thị | Cần giữ đúng time origin và đơn vị |
| Trường hợp nên dùng | Sự kiện xảy ra lúc nào | Đoạn xử lý mất bao lâu |
Đừng lưu riêng performance.now rồi gửi sang process khác để trừ trực tiếp với giá trị bên đó. Hai process có thể có mốc khác nhau. Với hệ thống phân tán, cần một thiết kế quan sát có hợp đồng thời gian và trace riêng.
Lỗi thường gặp và cách kiểm tra
- Trừ Date.now cho performance.now vì cả hai đều ghi đơn vị ms.
- Diễn giải duration chờ I/O thành CPU time.
- Kết luận tối ưu từ một lần chạy thao tác quá nhỏ.
- Coi nhiều chữ số thập phân là bằng chứng độ chính xác tương ứng trên mọi thiết bị.
Hãy lưu timestamp và duration thành hai trường có tên rõ ràng. Kiểm tra ranh giới đo, môi trường và số lượt quan sát trước khi dùng duration làm bằng chứng cho một thay đổi hiệu năng.

