Cấp phát bộ nhớ hoạt động như thế nào trong Ruby?
Ruby có bộ nhớ theo từng phần, được gọi là các trang, các đối tượng mới được lưu ở đây.
Sau đó…
Khi các trang này đầy, cần thêm bộ nhớ.
Ruby yêu cầu thêm bộ nhớ từ hệ điều hành với malloc
chức năng.
malloc
này chức năng là một phần của chính hệ điều hành, nhưng có những cách triển khai thay thế mà bạn có thể sử dụng.
Một trong những cách triển khai đó là tcmalloc của Google.
TCmalloc là một phần của bộ Công cụ Hiệu suất của Google.
Bạn có thể sử dụng các công cụ này để khám phá chính xác cách Ruby phân bổ bộ nhớ.
Và cảm ơn LD_PRELOAD
biến môi trường (trong Linux), chúng tôi có thể thay thế malloc
của hệ thống của bạn hàm với tcmalloc.
Như thế này :
LD_PRELOAD ="/ usr / lib / libtcmalloc.so" ruby -e "đặt 123"
Nhưng điều đó chỉ tải thư viện, nó chưa cho phép thu thập dữ liệu nào.
Hãy xem điều đó được thực hiện như thế nào.
Bật hồ sơ
Bạn có thể bật hồ sơ của tcmalloc bằng một biến môi trường bổ sung (HEAPPROFILE
).
LD_PRELOAD ="/ usr / lib / libtcmalloc.so" HEAPPROFILE =/ tmp / profile ruby -e "đặt 123"
Điều này sẽ tạo ra kết quả sau:
Bắt đầu theo dõi hồ sơ heap123Dumping heap vào /tmp/profile.0001.heap (Đang thoát, 2 MB đang được sử dụng)
Tại đây, bạn sẽ thấy xác nhận rằng trình cấu hình đã được kích hoạt.
Sau đó, chúng tôi thấy :
- Đầu ra của chương trình
- Tên tệp (
profile.0001.heap
) - Dung lượng bộ nhớ mà chương trình của chúng tôi sử dụng (
2 MB
)
Để đọc tệp này, bạn sẽ cần một công cụ khác đi kèm với tcmalloc.
pprof --text `which ruby` /tmp/profile.0001.heap | đầu -10
Điều này sẽ tạo ra kết quả sau:
Tổng:2,4 MB 1,1 44,7% 44,7% 1,1 44,7% 0x00005570fa4df074 0,7 27,8% 72,5% 0,7 27,8% 0x00005570fa4e0c09 0,4 15,3% 87,8% 0,4 15,3% 0x00005570fa4db460 0,1 5,9% 93,7% 0,1 5,9% 0x000055 3,2% 96,9% 0,1 % 0x00005570fa6349a0 0,0 1,4% 98,3% 0,0 1,4% 0x00005570fa589924 0,0 0,3% 98,6% 0,0 0,3% 0x00005570fa59c4f2 0,0 0,3% 98,8% 0,0 0,3% 0x00005570fa4db48a 0,0 0,2% 99,0% 0,0 0,2% 0x00005570fa59c4dbaa5 <0,0%>Chà, đó chỉ là một loạt các địa chỉ bộ nhớ! Bạn cần một phiên bản Ruby với các ký hiệu gỡ lỗi để có thể xem tên hàm.
Sau đó, bạn sẽ nhận được đầu ra này :
Sử dụng tệp cục bộ ruby Sử dụng tệp cục bộ /tmp/profile.0001.heap.Tổng:2,9 MB 1,0 36,2% 36,2% 1,0 36,2% objspace_xmalloc0 0,7 26,1% 62,4% 0,7 26,1% align_malloc 0,5 18,8% 81,1% 0,5 18,8% objspace_xcalloc 0,3 9,9% 91,0% 0,3 9,9% stack_chunk_alloc 0,1 3,7% 94,7% 0,1 3,7% objspace_xrealloc 0,1 2,7% 97,4% 0,1 2,7% Init_Method 0,0 1,3% 98,7% 0,0 1,7% onig_new_with_source 0,0 0,4% 99,2% 0,8 26,6% heap_page_allocate 0,0 0,2% 99,4 % 0.0 0,2% add_bitsetNhững gì bạn thấy ở đây là lượng bộ nhớ được phân bổ theo các chức năng của MRI.
Thật thú vị khi biết rằng
aligned_malloc
là hàm được sử dụng để cấp phát các trang mới cho các đối tượng Ruby,stack_chunk_alloc
được chính GC sử dụng trong giai đoạn đánh dấu vàobjspace_xmalloc0
/objspace_xcalloc
phân bổ không gian cho chuỗi, mảng và bất kỳ dữ liệu nào khác không phù hợp vớiRVALUE
cấu trúc.Bây giờ:
TCmalloc không biết gì về các đối tượng Ruby, điều duy nhất nó làm là theo dõi các lệnh gọi đến malloc, calloc &realloc để tìm ra dung lượng bộ nhớ được yêu cầu.
Nếu bạn muốn có một kết xuất đống ở cấp độ Ruby, bạn có thể sử dụng
ObjectSpace.dump_all
. Điều này cung cấp cho bạn một tệp JSON với tất cả các đối tượng trực tiếp trong ứng dụng của bạn và kích thước bộ nhớ của chúng.Nhưng cái gì
tcmalloc
có thể cho bạn thấy là hình dung của tất cả các hàm C yêu cầu bộ nhớ.pprof --web `which ruby` /tmp/profile.0001.heapThao tác này sẽ mở Chrome hoặc Firefox với tệp SVG trông giống như sau:
TCmalloc không chỉ cung cấp cho bạn khả năng lập hồ sơ tuyệt vời này mà khi sử dụng nó, bạn còn có thể tăng hiệu suất ứng dụng của mình lên 4-9%! Bạn cũng có thể thử
jemalloc
, là mộtmalloc
khác triển khai cũng bao gồm một trình mô tả.Tóm tắt
Bạn đã học cách sử dụng gperftools (Công cụ Hiệu suất của Google) để trực quan hóa và phân tích việc sử dụng bộ nhớ của trình thông dịch Ruby.
Cảm ơn vì đã đọc! 🙂