Trong quá trình phát triển ứng dụng hoặc đang vận hành nó trong môi trường production sẽ có lúc phát sinh ra nhiều vấn đề mà chúng ta không lường trước được. Khi ứng dụng được tung ra thị trường, chắc chắn lượng người dùng sẽ nhiều lên từng ngày, từ đó tạo ra sự đa dạng về hành vi lẫn dữ liệu người dùng thu thập được. Chúng kết hợp với nhau tạo ra nhiều trường hợp phát sinh lỗi mà quá trình kiểm thử trước đó không hề phát hiện ra.
Một trong số đó có thể kể đến như là tốc độ phản hồi API bỗng trở nên chậm chạp mặc dù lượng người sử dụng là không nhiều. Khi kiểm tra lại tính năng gây ra tình trạng đó, có vẻ bạn phát hiện ra hoặc đang nghi ngờ một hàm nào đó chiếm lượng thời gian xử lý lớn. Để chắc chắn là mình đúng thì tất nhiên phải đo được xem cụ thể là hàm đó tốn bao nhiêu thời gian để xử lý.
Có nhiều cách để biết hàm nào đang gây chậm hệ thống. Các ứng dụng APM với khả năng kiểm soát và chuẩn đoán ứng dụng của bạn rất tốt để kịp thời cảnh báo vấn đề. Một vài dịch vụ APM có tính năng thu thập hoặc cảnh báo theo thời gian thực nếu như chúng phát hiện ra một hàm nào đó đang mất quá nhiều thời gian để thực hiện, hoặc thời gian phản hồi của API là quá lâu. Nhưng đổi lại, giá thành của chúng không hề rẻ, hoặc nếu có miễn phí thì nhiều hạn chế sẽ phát sinh. Vì lẽ đó không phải ai cũng có điều kiện sử dụng APM, đó là lúc bạn cần đến một cách "xôi thịt" hơn nhưng lại hoàn toàn miễn phí mà ai cũng có thể tiếp cận được.
Date.now()
, console.time()
, performance.now()
, process.hrtime()
... là các hàm thường hay được sử dụng để đo khoảng thời gian mà hàm thực hiện. Về cơ bản, chỉ cần kẹp giữa hàm cần đo bằng chúng thì sẽ tính được thời gian thực thi.
Ví dụ sau dử dụng Date
để tính thời gian thực thi bằng cách trừ hai khoảng thời gian trước và sau khi hàm được chạy.
const start = Date.now();
await functionToBeMeasured();
const end = Date.now();
console.log(`Execution time: ${end - start} ms`);
Ngoài ra, đơn giản hơn thì dùng console.time
:
console.time('executionFunctionToBeMeasured');
await functionToBeMeasured();
console.timeEnd('executionFunctionToBeMeasured');
console.time
không mang lại độ chính xác cao. Nếu muốn độ chính xác theo phần nghìn giây, hãy sử dụng hàm mạnh mẽ hơn với performance.now()
hoặc process.hrtime()
nếu sử dụng Node.js.
const start = performance.now();
await functionToBeMeasured();
const end = performance.now();
console.log(`Execution time: ${end - start} ms`);
Sau khi biết cách đo thời gian, một vấn đề khác nảy sinh đó chính là cần phải đặt hàm cần đo kẹp giữa hai hàm tính thời gian. Điều này gây ra sự xáo trộn mã trong dự án của bạn, phải sửa nhiều hơn, mã trở nên cồng kềnh hơn và khó kiểm soát.
Ý tưởng lúc này là viết một hàm để gói gọn tính năng đo thời gian thực thi. Đầu vào là một hàm cần tính còn đầu ra là kết quả của hàm đó cùng với thời gian thực thi. Một hàm gì đó trông giống như dưới đây:
calcExecuteTime(functionToBeMeasured);
functionToBeMeasured
đôi khi là hàm có cả tham số, vì thế hãy sửa lại một chút.
calcExecuteTime(() => functionToBeMeasured(arg1, arg2...));
Nếu trong functionToBeMeasured
có sử dụng this
, hãy thêm một tham số context để nhận this
từ nơi gọi.
calcExecuteTime(context, () => functionToBeMeasured(arg1, arg2...));
Cuối cùng, nên thêm một tham số name
để xác định được cuộc gọi hàm từ đâu.
calcExecuteTime(name, context, () => functionToBeMeasured(arg1, arg2...));
Hàm calcExecuteTime
có thể giống như sau:
const calcExecuteTime = async (name, context, fn) => {
const start = process.hrtime();
const result = await fn.call(context);
const stop = process.hrtime(start);
const executeTime = (stop[0] * 1e9 + stop[1]) / 1e9;
console.log(`${name} execution time: ${executeTime}s`);
return result;
};
Bây giờ hãy thử gọi hàm xem:
calcExecuteTime("Execute ToBeMeasured", this, () => functionToBeMeasured(arg1, arg2...));
// Execute ToBeMeasured execution time: 0.000178s
Bạn cũng có thể sửa lại hàm tùy vào mục đích, ví dụ thay vì console.log
thì hãy logging lại thời gian thực hiện hàm vào đâu đó. Hoặc nâng cấp hàm lên ví dụ như thêm một cờ bật/tắt tính năng tính thời gian.
Tham khảo:
Bí mật ngăn xếp của Blog
Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!
Đăng ký nhận thông báo bài viết mới
Xin chào, tôi tên là Hoài - một anh Dev kể chuyện bằng cách viết ✍️ và làm sản phẩm 🚀. Với nhiều năm kinh nghiệm lập trình, tôi đã đóng góp một phần công sức cho nhiều sản phẩm mang lại giá trị cho người dùng tại nơi đang làm việc, cũng như cho chính bản thân. Sở thích của tôi là đọc, viết, nghiên cứu... Tôi tạo ra trang Blog này với sứ mệnh mang đến những bài viết chất lượng cho độc giả của 2coffee.dev.Hãy theo dõi tôi qua các kênh LinkedIn, Facebook, Instagram, Telegram.
Bình luận (1)