Có một số bài báo về cách tìm rò rỉ bộ nhớ.
Nhưng làm thế nào về việc tạo một cái?
Tôi nghĩ đây sẽ là một bài tập thú vị để bạn biết rò rỉ bộ nhớ trông như thế nào trong Ruby.
Hãy xem một số ví dụ.
Rò rỉ đơn giản
Chúng ta có thể tạo rò rỉ bộ nhớ bằng cách chỉ cần thêm các đối tượng mới vào một mảng.
Như thế này :
a = [] b = {} loop { sleep(1) 10_000.times { a << "abc" } puts GC.stat(b)[:heap_live_slots] }
Điều này tạo ra 10k chuỗi mỗi giây và nó in ra một số lượng đối tượng:
285051 295052 305053 315054 325055 335056 345057 355058
Số lượng tiếp tục tăng lên vì GC không thể thu thập các chuỗi này, chúng đang được tham chiếu bởi mảng chứa (a
).
Nếu a
vượt ra khỏi phạm vi sẽ cho phép GC thu thập tất cả "abc"
này dây. Bạn có thể kiểm tra điều này với ví dụ trên bằng cách đặt a
đến nil, sau đó chạy GC.start
.
Bạn có thể tìm thấy một ví dụ trực tiếp tại đây, chỉ cần nhấp vào run
để xem kết quả.
Rò rỉ tiện ích mở rộng C
Khi bạn tạo một đối tượng từ Ruby, GC sẽ theo dõi dung lượng bộ nhớ mà nó đang sử dụng, nhưng khi sử dụng phần mở rộng C, Ruby không kiểm soát được điều gì sẽ xảy ra.
Nếu bạn tạo một phần mở rộng C như thế này:
#include <ruby.h> #include "extconf.h" void *ptr; void Init_extension() { allocate_memory(); } void allocate_memory() { for(int i = 0; i < 10000; i++) { ptr = malloc(1000); } }
allocate_memory()
hàm sẽ làm rò rỉ bộ nhớ vì nó đang sử dụng malloc
&nó không gọi free
để giải phóng bộ nhớ đó.
Như bạn có thể thấy ở đây:
`ps -o rss -p #{$$}`.lines.last # "49036" require './extension' `ps -o rss -p #{$$}`.lines.last # "89512"
Loại rò rỉ này sẽ không hiển thị trên bất kỳ kết xuất heap nào hoặc trên GC.stat
, nhưng bạn sẽ thấy mức sử dụng bộ nhớ tăng lên.
Tóm tắt
Bây giờ bạn đã biết rò rỉ bộ nhớ trông như thế nào, hy vọng điều đó sẽ giúp bạn tìm ra lỗi nhanh hơn nếu bạn gặp sự cố này. Btw Ruby 2.4.1 bị rò rỉ bộ nhớ đã biết, vì vậy bạn có thể muốn nâng cấp nếu đang sử dụng phiên bản cụ thể này.
Bạn có bất kỳ câu hỏi, phản hồi hoặc một câu chuyện gỡ lỗi rò rỉ bộ nhớ thú vị nào không? Để lại bình luận bên dưới 🙂
Cảm ơn vì đã đọc!