2009-08-31 26 views
33

Tôi đã viết một dịch vụ mạng liên tục trong Perl chạy trên Linux.Perl sử dụng bộ nhớ hồ sơ và phát hiện rò rỉ?

Thật không may, khi nó chạy, kích thước ngăn xếp thường trú của nó (RSS) chỉ phát triển và phát triển, và phát triển, từ từ nhưng chắc chắn. Điều này là mặc dù nỗ lực siêng năng của tôi một phần để xóa tất cả các khóa băm không cần thiết và xóa tất cả các tham chiếu đến các đối tượng mà nếu không sẽ gây ra số lượng tham chiếu vẫn còn tại chỗ và cản trở thu gom rác thải. Có bất kỳ công cụ tốt nào để lược tả việc sử dụng bộ nhớ được liên kết với các nguyên thủy dữ liệu gốc khác nhau, các đối tượng tham chiếu băm may mắn, v.v. trong một chương trình Perl không? Không. Bạn sử dụng những gì để theo dõi rò rỉ bộ nhớ?

Tôi không thường xuyên dành thời gian trong trình gỡ lỗi Perl hoặc bất kỳ trình thu thập thông tin tương tác nào khác nhau, do đó, một phản hồi ấm áp, nhẹ nhàng, không bí truyền sẽ được đánh giá cao. :-)

+0

Bạn đã tìm ra? Đoán tốt nhất của tôi cho các thông tin bạn đã cung cấp là có một thư viện (đưa vào thông qua một số dynaloader module) đó là thủ phạm ... – Ether

+0

Điều này dường như đã trở thành kinh điển "tìm một rò rỉ bộ nhớ" câu hỏi, kể từ câu trả lời của tôi từ khác câu hỏi tương tự đã được sáp nhập ở đây :) Tôi đã không thực sự trả lời một câu hỏi ba lần; nhiều chủ đề đã được hợp nhất với nhau theo thời gian. – Ether

+0

Trượt lưỡi ... bạn có nghĩa là "Kích thước thiết lập thường trú" ... số này không liên quan đến ngăn xếp –

Trả lời

13

Bạn có thể có tham chiếu vòng tròn ở một trong các đối tượng của mình. Khi bộ thu gom rác đi kèm để giải quyết đối tượng này, tham chiếu vòng tròn có nghĩa là mọi thứ được nhắc tới bởi tham chiếu đó sẽ không bao giờ được giải phóng. Bạn có thể kiểm tra các tham chiếu vòng tròn với Devel::CycleTest::Memory::Cycle. Một điều cần cố gắng (mặc dù nó có thể nhận được đắt tiền trong mã sản xuất, vì vậy tôi muốn vô hiệu hóa nó khi một lá cờ debug không được thiết lập) đang kiểm tra tài liệu tham khảo tròn bên trong destructor cho tất cả các đối tượng của bạn:

# make this be the parent class for all objects you want to check; 
# or alternatively, stuff this into the UNIVERSAL class's destructor 
package My::Parent; 
use strict; 
use warnings; 
use Devel::Cycle; # exports find_cycle() by default 

sub DESTROY 
{ 
    my $this = shift; 

    # callback will be called for every cycle found 
    find_cycle($this, sub { 
      my $path = shift; 
      foreach (@$path) 
      { 
       my ($type,$index,$ref,$value) = @$_; 
       print STDERR "Circular reference found while destroying object of type " . 
        ref($this) . "! reftype: $type\n"; 
       # print other diagnostics if needed; see docs for find_cycle() 
      } 
     }); 

    # perhaps add code to weaken any circular references found, 
    # so that destructor can Do The Right Thing 
} 
+1

PS. Bạn có thể làm suy yếu một tham chiếu hiện có (để cho phép một destructor làm việc phép thuật của nó thông qua các chu kỳ) với Scalar :: Util :: weaken() - http://search.cpan.org/~gbarr/Scalar-List-Utils-1.21 /lib/Scalar/Util.pm – Ether

+2

Hi Ether - đã thử UNIVERSAL :: DESTROY(), điều hành dịch vụ trong một thời gian dài và đập vào nó, và không nhận được gì cả. Trong khi đó, RSS đang leo lên. Điều gì khác nó có thể được nếu không phải là một vấn đề tham khảo vòng tròn? –

+2

Tôi thực sự không chắc chắn làm thế nào tìm kiếm rò rỉ bộ nhớ trong một destructor sẽ làm bạn bất kỳ ưu đãi. Nếu bạn đang bị rò rỉ, DESTROY sẽ không bao giờ được gọi. –

9

Bạn có thể sử dụng Devel::Leak để tìm kiếm rò rỉ bộ nhớ. Tuy nhiên, tài liệu là khá thưa thớt ... ví dụ, chỉ cần một trong những nơi có được tham chiếu xử lý $ để vượt qua để Devel::Leak::NoteSV()? f Tôi tìm câu trả lời, tôi sẽ chỉnh sửa câu trả lời này.

Ok nó quay ra rằng việc sử dụng mô-đun này là khá đơn giản (mã bị đánh cắp trắng trợn từ Apache::Leak):

use Devel::Leak; 

my $handle; # apparently this doesn't need to be anything at all 
my $leaveCount = 0; 
my $enterCount = Devel::Leak::NoteSV($handle); 
print STDERR "ENTER: $enterCount SVs\n"; 

# ... code that may leak 

$leaveCount = Devel::Leak::CheckSV($handle); 
print STDERR "\nLEAVE: $leaveCount SVs\n"; 

Tôi muốn đặt càng nhiều mã càng tốt ở phần giữa, với việc kiểm tra leaveCount như gần cuối của thực thi (nếu bạn có một) càng tốt - sau khi hầu hết các biến đã được deallocated càng tốt (nếu bạn không thể có được một biến ngoài phạm vi, bạn có thể gán undef cho nó để miễn phí bất cứ điều gì nó đã trỏ đến).

+0

biến không nhất quán được sử dụng trong ví dụ, ví dụ: $ leave so với $ leaveCount – Lot105

4

gì tiếp theo để thử (không chắc chắn nếu điều này sẽ được đặt tốt nhất trong một chú thích sau khi câu hỏi của Alex trên mặc dù): Những gì tôi muốn thử tiếp theo (trừ Devel :: rò rỉ):

Cố gắng loại bỏ " không cần thiết "các phần của chương trình của bạn, hoặc phân đoạn nó thành các tệp thực thi riêng biệt (chúng có thể sử dụng các tín hiệu để giao tiếp hoặc gọi cho nhau bằng các đối số dòng lệnh) - mục tiêu là để làm lu mờ một tệp thực thi vẫn thể hiện hành vi xấu. Nếu bạn chắc chắn đó không phải là mã của bạn đang làm việc đó, hãy giảm số lượng mô-đun bên ngoài bạn đang sử dụng, đặc biệt là các mô-đun có triển khai XS. Nếu có lẽ đó là mã của riêng bạn, hãy tìm bất cứ điều gì có khả năng tanh:

  • chắc chắn bất kỳ sử dụng Inline :: C hoặc XS đang
  • sử dụng trực tiếp tài liệu tham khảo, ví dụ\@list hoặc \%hash, thay vì tham chiếu preallocated như [qw (foo bar)] (trước đây tạo một tham chiếu khác có thể bị mất, sau này, chỉ có một tham chiếu phải lo lắng, thường được lưu trữ trong một địa phương lexical vô hướng
  • biến thao tác gián tiếp, ví dụ như $$foo nơi $foo được sửa đổi, mà có thể gây ra autovivication của các biến (mặc dù bạn cần phải vô hiệu hóa strict 'refs' kiểm tra)
2

Tôi mới sử dụng NYTProf như một hồ sơ cho một ứng dụng Perl lớn. Nó không theo dõi việc sử dụng bộ nhớ, nhưng nó theo dõi tất cả các đường dẫn mã thực thi giúp tìm ra nơi rò rỉ bắt nguồn. Nếu những gì bạn đang bị rò rỉ là tài nguyên khan hiếm như kết nối cơ sở dữ liệu, truy tìm nơi chúng được phân bổ và đóng cửa sẽ đi một chặng đường dài hướng tới việc tìm kiếm rò rỉ.

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