2009-01-09 30 views
34

Perl sử dụng tính tham chiếu cho GC, và thật dễ dàng để thực hiện một tham chiếu vòng tròn do tai nạn. Tôi thấy rằng chương trình của tôi dường như đang sử dụng nhiều bộ nhớ hơn, và nó có thể sẽ tràn sau một vài ngày.Làm thế nào tôi có thể tìm thấy rò rỉ bộ nhớ trong chương trình Perl dài hạn?

Có cách nào để gỡ lỗi rò rỉ bộ nhớ trong Perl không? Gắn với một chương trình và nhận được số lượng các đối tượng của các loại khác nhau sẽ là một khởi đầu tốt. Nếu tôi biết đối tượng nào nhiều hơn nhiều so với dự kiến, tôi có thể kiểm tra tất cả các tham chiếu đến chúng và hy vọng khắc phục sự cố rò rỉ.

Trả lời

34

Có thể có liên quan rằng Perl không bao giờ cung cấp cho bộ nhớ tự quay trở lại hệ thống: Tất cả lên đến malloc() và tất cả các quy tắc liên quan đến điều đó.

Biết cách malloc() cấp phát bộ nhớ là quan trọng để trả lời câu hỏi lớn hơn và thay đổi từ hệ thống sang hệ thống, nhưng nói chung hầu hết các triển khai malloc() được tối ưu hóa cho các chương trình phân bổ và deallocating theo thứ tự giống như ngăn xếp. Perl sử dụng tính toán tham chiếu để theo dõi bộ nhớ có nghĩa là deallocations có nghĩa là (không giống như ngôn ngữ dựa trên GC sử dụng malloc() bên dưới) thực tế không phải là tất cả khó khăn để cho biết nơi deallocation sẽ xảy ra và theo thứ tự nào.

Nó có thể là bạn có thể tổ chức lại chương trình của bạn để tận dụng lợi thế của fact- này bằng cách gọi undef($old_object) một cách rõ ràng - và theo thứ tự đúng, một cách tương tự như cách C-lập trình viên nói free(old_object);

Đối dài các chương trình đang chạy (ngày, tháng, v.v.), nơi tôi tải các chu kỳ tải/sao chép/đổ, tôi thu thập dữ liệu bằng cách sử dụng exit() and exec() và không thể giải quyết được toàn bộ dữ liệu của tôi (sử dụng Storable) và mô tả tệp (sử dụng $^F) và exec($0) - thường có biến môi trường được đặt là $ENV{EXEC_GC_MODE} và bạn có thể cần một cái gì đó tương tự ngay cả khi bạn không có bất kỳ rò rỉ của riêng bạn chỉ đơn giản là vì Perl bị rò rỉ các khối nhỏ mà hệ thống của bạn malloc() không thể tìm ra cách trả lại.

Tất nhiên, nếu bạn bị rò rỉ trong của bạn, thì phần còn lại của lời khuyên của tôi có liên quan hơn một chút. Ban đầu, nó được đăng to another question on this subject, nhưng không được rõ ràng bao gồm các chương trình chạy dài.


Mọi rò rỉ bộ nhớ chương trình perl sẽ là XS lưu giữ tham chiếu hoặc cấu trúc dữ liệu hình tròn. Devel::Cycle là một công cụ tuyệt vời để tìm tham khảo vòng tròn, nếu bạn biết cấu trúc nào có khả năng chứa các vòng lặp. Devel::Peek có thể được sử dụng để tìm các đối tượng có số lượng tham chiếu cao hơn mong đợi.

Nếu bạn không biết nơi nào khác để xem, Devel::LeakTrace::Fast có thể là một địa điểm tốt đầu tiên, nhưng bạn sẽ cần một perl được xây dựng để gỡ lỗi.

Nếu bạn nghi ngờ bị rò rỉ bên trong XS-không gian, nó khó khăn hơn nhiều, và Valgrind có lẽ sẽ là đặt cược tốt nhất của bạn. Test::Valgrind có thể giúp bạn giảm số lượng mã bạn cần tìm kiếm, nhưng điều này sẽ không hoạt động trên Windows, vì vậy bạn phải chuyển (ít nhất là phần bị rò rỉ) sang Linux để thực hiện việc này.

+0

http://search.cpan.org/perldoc?Scalar::Util 'weaken' –

+0

Làm thế nào để 'weaken' giúp bạn? – geocar

+0

@geocar, điều này thật tuyệt vời! Phương pháp mạnh mẽ duy nhất cho vấn đề không thể tránh khỏi của rò rỉ bộ nhớ trong các chương trình perl phức tạp mà tôi biết. –

3

Có vẻ như mô-đun cpan Devel::Cycle là những gì bạn đang tìm kiếm. Nó đòi hỏi phải thực hiện một số thay đổi đối với mã của bạn, nhưng nó sẽ giúp bạn tìm thấy các tham chiếu của bạn mà không có quá nhiều vấn đề.

2

valgrind là một ứng dụng Linux tuyệt vời, có vị trí rò rỉ bộ nhớ trong mã đang chạy. Nếu mã Perl của bạn chạy trên Linux, bạn nên kiểm tra nó.

+0

Tôi không nghĩ điều đó sẽ hiệu quả. Perl là một ngôn ngữ thông dịch. Sẽ không valgrind chỉ trỏ đến các cuộc gọi phân bổ bộ nhớ trong thông dịch viên Perl? – Ferruccio

+0

không có valgrind có thể làm việc với Perl, chỉ cần sử dụng các tùy chọn phù hợp. nó được ghi lại. nó cần đính kèm chính nó vào tệp thực thi được biên dịch chứ không phải là nhị phân perl. – casey

+0

valgrind sẽ tìm thấy rò rỉ bộ nhớ trong mã XS, nhưng không phải trong mã Perl. Sử dụng Devel :: Cycle hoặc Devel :: Rò rỉ cho điều đó. – rjh

2

Ngoài các nhận xét khác, bạn có thể tìm thấy số Perl Memory Use talk tại LPW2013 hữu ích của mình. Tôi khuyên bạn nên xem the screencast vì nó giải thích các trang trình bày và có một số hình ảnh dễ thương và một số Q & A ở cuối.

Tôi cũng khuyên bạn nên xem xét mô-đun Paul Evans Devel::MAT mà tôi đề cập trong cuộc trò chuyện.

Các vấn đề liên quan