Đo lường thời gian thực hiện hàm trong Javascript một cách thanh lịch

Đo lường thời gian thực hiện hàm trong Javascript một cách thanh lịch

Tin ngắn hàng ngày dành cho bạn
  • openai/codex là một dự án mã nguồn mở mới nhất của OpenAI, ngay sau khi họ công bố hai mô hình mới nhất là o3 và o4 mini. Nghe nói cả o3 và o4 mini này rất thích hợp làm Agent nên tung ra codex như một dạng Agent nhỏ nhẹ chạy ngay trong Terminal luôn.

    Về tính ứng dụng, vì nó là Agent nên nó có thể đọc/thêm/sửa/xoá nội dung tệp của bạn luôn. Ví dụ.

    codex "explain this codebase to me"

    Hoặc tích hợp vào pipe line của CI/CD.

    - name: Update changelog via Codex run: | npm install -g @openai/codex export OPENAI_API_KEY="${{ secrets.OPENAI_KEY }}" codex -a auto-edit --quiet "update CHANGELOG for next release"

     À quên mất, phải dùng API của OpenAI nha 😆

    » Xem thêm
  • Có thể nhiều người chưa biết, OpenAI đã mở trang học viện riêng để giúp người dùng học tập và khai thác được tối đa sức mạnh các mô hình ngôn ngữ của họ.

    OpenAI Academy

    » Xem thêm
  • Mới sáng ra đã có tin giật gân: OpenAI muốn mua lại Windsurf với giá 3 tỉ đô 😳

    » Xem thêm

Vấn đề

Trong quá trình phát triển hoặc vận hành hệ thống phần mềm, có những lúc phát sinh ra nhiều vấn đề mà chúng ta không lường trước được. Một khi ứng dụng được tung ra thị trường, lượng người dùng tăng theo từng ngày tạo ra sự đa dạng về hành vi lẫn dữ liệu sinh ra trong hệ thống. Chúng kết hợp với nhau để bùng nổ những lỗi mà quá trình kiểm thử trước đó không hề biết.

Một trong số đó có thể kể đến 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, có vẻ bạn phát hiện ra hoặc nghi ngờ một hàm nào đó mất thời gian xử lý. Để cho chắc chắn thì tất nhiên phải làm cách nào đó để đo xem hàm đó tốn bao nhiêu thời gian xử lý. Có nhiều cách để tìm xem hàm nào đang tiêu tốn thời gian. Nhiều ứng dụng APM có khả năng kiểm soát và chuẩn đoán hiệu suất ứng dụng rất tốt, kịp thời cảnh báo vấn đề đến người quản trị. Một vài dịch vụ APM còn 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 để xử lý. Hay chí ít là cảnh báo thời gian phản hồi quá lâu. Nhưng đổi lại giá thành của chúng không hề rẻ, nếu có miễn phí thì nhiều hạn chế kèm theo buộc phải nâng cấp nếu muốn dùng thoải mái. 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í, ai cũng có thể tiếp cận được.

Đo lường thời gian thực hiện hàm trong Javascript

Date.now(), console.time(), performance.now(), process.hrtime()... là các hàm thường được dùng để đo khoảng thời gian thực hiện lệnh. Về cơ bản, chỉ cần kẹp giữa hàm cần đo thì sẽ tính được thời gian thực thi.

Ví dụ dùng Date để tính thời gian thực thi của hàm functionToBeMeasured giống như sau:

const start = Date.now();

await functionToBeMeasured();

const end = Date.now();
console.log(`Execution time: ${end - start} ms`);

Cũng có thể làm tương tự với console.time:

console.time('executionFunctionToBeMeasured');

await functionToBeMeasured();

console.timeEnd('executionFunctionToBeMeasured');

Tuy vậy, 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() trong trình duyệt 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 nguyên lý đo thời gian, vấn đề là làm cách nào để dùng. Chẳng lẽ cứ phải tìm và kẹp giữa hàm bằng 2 dòng startend? Tin vui là không cần phải làm thế. Ý tưởng lúc này là viết một hàm gói gọn hàm khác để đo thời gian. Hàm này có đầu vào là một hàm cần đo thời gian, đầu ra là kết quả của hàm đó kèm với thời gian thực thi. Một cái gì đó trông giống như dưới đây:

calcExecuteTime(functionToBeMeasured);

Với calcExecuteTime làm hàm cần tạo ra. functionToBeMeasured là hàm cần do thời gian. Đôi khi functionToBeMeasured 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ố ngữ cảnh để nhận this từ nơi gọi hàm, đảm bảo ngữ cảnh cho hàm.

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

Tổng hợp lại, 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ó thể sửa lại hàm tuỳ thích, ví dụ thay vì console.log thì ghi lại thời gian thực hiện hàm vào đâu đó, ví dụ như một tệp .log hoặc bắn lên dịch vụ đám mây nào đó. Ngoài ra có thể thêm một cờ bật/tắt tính năng tính năng đo thời gian khi nó không cần thiết nữa.

Tham khảo:

Cao cấp
Hello

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!

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!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (1)

Nội dung bình luận...
Avatar
Tuan Nguyen2 năm trước
Thử chạy cái hàm đó trong 1_000_000 rồi tính trung bình sau đó đem so với chạy cái hàm đó 1 lần. Kết quả sẽ bất ngờ đó. Đó là cơ chế của node
Trả lời
Avatar
Xuân Hoài Tống2 năm trước
Bạn ơi đó là cơ chế gì vậy ạ?