Từ khi mới bắt đầu lập trình, tôi đã bị ám ảnh về vấn đề hiệu suất của chương trình mà mình viết ra. Không biết mình viết như thế này đã tốt chưa, đã tối ưu chưa, liệu nó có thể chịu tải được bao nhiêu người dùng cùng lúc... Đó cũng là viên gạch đầu tiên đặt nền móng cho việc đi tìm hiểu sâu hơn về cách hoạt động của các ngôn ngữ lập trình nói chung, hay là Node.js nói riêng.
Trải qua nhiều năm tháng, tham gia nhiều dự án và nhận ra việc tối ưu hiệu suất không phải lúc nào cũng dễ. Có nhiều thứ cần phải quan tâm bên cạnh việc suy tư cho những dòng code. Một mặt là do tối ưu tốn khá nhiều thời gian, mặt khác là có thứ cần ưu tiên hơn là Trải nghiệm người dùng.
Tuy vậy, tối ưu hiệu suất phần mềm không bao giờ là thừa. Bạn không nên chạy đua với thời gian để tạo ra rào cản về hiệu suất bằng những đoạn mã ẩu. Mà cần dành thời gian để tìm hiểu xem những lý do nào dễ gây ra tình trạng ì ạch của phần mềm. Sau đó, tận dụng các công cụ gỡ lỗi và lập hồ sơ hiệu suất để dễ dàng cho quá trình tối ưu sau này.
Trong Node.js - Clinic.js hẳn là một cái tên không còn xa lạ với nhiều người. Đây là một công cụ mã nguồn mở giúp chuẩn đoán để điều trị các căn "bệnh" về hiệu suất dành riêng cho Node. Bài viết ngày hôm nay, chúng ta hãy xem Clinic.js có thể làm được những gì nhé.
Clinic.js là một công cụ giúp chẩn đoán và xác định các vấn đề về hiệu suất cho các ứng dụng viết bằng Node.js. Mặc dù Clinic.js không còn được duy trì tích cực nhưng nó vẫn có nhiều tính năng hết sức mạnh mẽ để chuẩn đoán các căn bệnh thường gặp. Tài liệu của Clinic.js đã hướng dẫn rất chi tiết về cách dùng vậy nên tốt nhất bạn đọc nên tham khảo trên trang tài liệu chính thức, còn ở đây, tôi chỉ đơn giản là tổng hợp lại những gì Clinic.js có thể làm được.
Khi nói về nguyên nhân làm giảm hiệu suất thì về cơ bản là do sử dụng quá nhiều bộ nhớ, sử dụng quá nhiều CPU hoặc các vấn đề về nút thắt cổ chai. Chúng ta biết rằng máy tính chỉ gồm có số lượng tài nguyên có hạn như bộ nhớ, cpu, disk... Nếu như sử dụng hết thì chắc chắn máy tính sẽ không hoạt động được như bình thường nữa, từ đó gây ảnh hưởng đến toàn bộ hệ thống nơi phần mềm của chúng ta đang chạy. Vì thế, mấu chốt là làm sao phân bổ và sử dụng tài nguyên cho hợp lý.
Đầu tiên hãy nói về việc sử dụng bộ nhớ. Càng nhiều bộ nhớ được cấp phát, khả năng chương trình càng trở nên chậm chạp. Tưởng tượng mỗi lượt xử lý truy vấn cấp phát 1MB bộ nhớ thì 1000 truy vấn vào cùng lúc sẽ tốn bao nhiêu? Đúng vậy, là 1GB!
Đã là chương trình thì phải sử dụng bộ nhớ. Ngày nay chúng ta có rất nhiều ngôn ngữ lập trình sử dụng bộ thu gom rác tự động. Tức là rác sẽ được thu gom sau một thời gian nào đó không sử dụng. So với cấp phát thủ công có phần mất thời gian và phức tạp. Tuy nhiên điều đó chưa hẳn là tốt, nhiều khi bộ thu gom rác không thể giải phóng hết bộ nhớ thừa thãi, gây ra tình trạng rò rĩ bộ nhớ (memory leak). Phải nói rằng trong Node.js, tình trạng này xảy ra rất thường xuyên do cách phân bổ bộ nhớ của Node.js cũng như hệ thống thư viện.
Clinic.js có tính năng gọi là Heap Profiler giúp dễ dàng thống kê lại số lượng bộ nhớ được cấp phát. Từ đó giúp bạn dễ khoanh vùng vị trí nào đang sử dụng quá nhiều bộ nhớ hoặc bị "leak".
Ví dụ sau khi chạy phân tích, chúng ta nhận được một bảng thống kê như dưới đây.
Mỗi khối đại diện cho cho các lệnh gọi của một hàm. Khối nào càng lớn chứng tỏ bộ nhớ sử dụng càng nhiều. Dựa vào biểu đồ này chúng ta có thể dễ dàng tìm ra vị trí của chúng vì tất cả đều thể hiện một cách rõ ràng.
Tiếp theo là CPU - đóng vai trò quan trọng trong tốc độ xử lý. Chúng ta đều biết Node.js chỉ có một luồng chính, nếu nó bị chặn sẽ gây ra tình trạng CPU tăng liên tục, dẫn đến nghẽn cổ chai. Nếu thấy ứng dụng phản hồi chậm hoặc chậm hơn nữa khi lượng người dùng tăng lên, khả năng là CPU đang quá cao, hoặc vòng lặp sự kiện (event loop) đang bị chặn.
Clinic.js cung cấp Doctor giúp chúng ta thống kê lại các thông số như là CPU, Memory, Event Loop... hoạt động như thế nào, có hiệu quả hay không.
Ví dụ dưới đây là kết quả sau khi chạy Doctor.
Clinic.js ngay lập tức chỉ ra rằng vòng lặp sự kiện đang gặp vấn đề vì nó liên tục bị chặn trong vòng 300ms. Để biết tại sao lại bị chặn và bị chặn ở đâu chúng ta nên sử dụng tiếp tính năng Flame.
Qua năm tháng, nhiều tính năng được thêm vào, nhiều người tham gia vào quá trình phát triển có thể khiến cho ứng dụng trở nên "dày" hơn. Hay nói cách khác là ngày càng phức tạp hơn. Một hàm có thể được hàm khác gọi, hàm khác lại có thể được hàm khác nữa gọi... lớp này gọi lớp kia và cứ như thế nếu xảy ra vấn đề về hiệu suất, thật khó để biết chính xác vấn đề nằm ở đâu.
Flame là một tính năng cực kỳ phù hợp trong trường hợp này. Flame phân tích và hiển thị ra chính xác vấn đề nằm ở đâu, kể cả chúng có lồng nhau như thế nào đi nữa.
Ví dụ kết quả của Flame như dưới đây.
Trong đó các dòng màu trắng thể hiện cho mã do bạn viết, màu xanh là mã của thư viện trong node_modules và màu xám là mã của Node.js. Thông thường màu trắng và xanh thường chiếm nhiều thời gian xử lý nhất. Bạn sẽ dễ dàng nhận ra vị trí cần tối ưu ở màu trắng hoặc cân nhắc việc đổi thư viện nếu như màu xanh đang quá nhiều.
Cuối cùng một tính năng khá thú vị khác mà cline.js cung cấp đó chính là Bubbleprof. Nó vẽ ra một bản đồ chứa những quả bong bóng đại diện cho một nhóm các hoạt động không đồng bộ. Bong bóng càng to chứng tỏ hoạt động không đồng bộ ở đó càng lớn.
Bubbleprof được dùng để tìm ra các nút thắt cổ chai bên trong ứng dụng. Bằng cách chỉ ra thành phần nào đang chiếm quá nhiều thời gian xử lý. Bubbleprof là tính năng nâng cao vì vậy bạn nên tham khảo hướng dẫn sử dụng từ trang tài liệu.
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
Bình luận (0)