2012-01-03 21 views
9

Chúng tôi có một codebase perl khá lớn.Tôi có thể sử dụng dtrace trên OS X 10.5 để xác định xem phần subsl của tôi có gây ra sự phân bổ bộ nhớ nhất không?

Một số quy trình chạy trong nhiều giờ (công việc ETL) đột nhiên bắt đầu tiêu tốn RAM nhiều hơn bình thường. Phân tích các thay đổi trong bản phát hành có liên quan là một quá trình chậm và bực bội. Tôi hy vọng sẽ xác định thủ phạm bằng cách sử dụng phân tích tự động hơn.

Môi trường sống của chúng tôi là perl 5.14 trên Debian squeeze.

Mặc dù vậy, tôi có quyền truy cập vào rất nhiều máy OS X 10.5. Dtrace và perl dường như chơi cùng nhau độc đáo trên nền tảng này. Dường như sử dụng dtrace trên Linux đòi hỏi phải khởi động nhiều công việc hơn. Tôi hy vọng rằng các mẫu phân bổ bộ nhớ sẽ giống nhau giữa hệ thống sống của chúng ta và hệ thống dev OS X - hoặc ít nhất là đủ tương tự để giúp tôi tìm ra nguồn gốc của việc sử dụng bộ nhớ mới này.

boong trượt này:

https://dgl.cx/2011/01/dtrace-and-perl

cho thấy làm thế nào để sử dụng dtrace làm hiển thị số gọi đến malloc theo tiểu perl. Tôi quan tâm đến việc theo dõi tổng số lượng bộ nhớ mà perl phân bổ trong khi thực hiện mỗi phụ trong suốt vòng đời của một quá trình.

Bất kỳ ý tưởng nào về cách thực hiện điều này?

+0

Điều này> có thể astletron

+0

Hrm. Điều đó đang làm> một cái gì đó astletron

+0

Tôi nghĩ rằng tôi có thể làm việc này. Có một vấn đề trong cách tôi đang chạy dtrace, không phải trong chương trình D của tôi. Tôi nghĩ rằng đầu ra tôi có là số byte được yêu cầu bởi malloc được chia nhỏ theo tên của phụ và tệp phụ nằm ở vị trí phụ đó là cuối cùng cho mỗi phụ được nhập trước malloc. Điều này không hoàn toàn đơn giản, nhưng có vẻ hữu ích về mặt hướng. Vẫn có thể sử dụng dữ liệu đầu vào từ bất kỳ ninja nào đã xảy ra để xác thực rằng tác phẩm của tôi ở ngay tại đây. – astletron

Trả lời

2

Câu trả lời cho câu hỏi là 'có'. Dtrace có thể được sử dụng để phân tích việc sử dụng bộ nhớ trong một quá trình perl.

Đoạn mã này:

https://github.com/astletron/perl-dtrace-malloc/blob/master/perl-malloc-total-bytes-by-sub.d

ca khúc cách sử dụng bộ nhớ tăng giữa cuộc gọi và trở lại của mỗi phụ trong một chương trình. Như một tiền thưởng thêm, dtrace dường như sắp xếp đầu ra cho bạn (ít nhất là trên OS X). Mát mẻ.

Cảm ơn tất cả những gì đã được lồng tiếng. Tôi đã tự trả lời câu hỏi này là câu hỏi thực sự cụ thể đối với dtrace/perl.

+0

Xin chào, bạn có thể giải thích điều gì đang xảy ra trong đoạn mã của mình không? Mã perl chính của bạn ở đâu? – user13107

+0

Đoạn mã đó được viết bằng D, ngôn ngữ kịch bản lệnh dtrace. Nó ghi lại ngăn xếp cuộc gọi phụ perl trong một mảng. Mỗi khi malloc được gọi, số lượng bộ nhớ được yêu cầu được thêm vào tổng số tiền liên quan đến subl hiện tại. Khi chương trình được kết thúc dtrace'd, tổng số lượng bộ nhớ được yêu cầu thông qua malloc trong quá trình thực hiện của mỗi phụ được in ra.Tôi nghĩ rằng điều này sẽ làm việc với bất kỳ mã perl (hoặc bất kỳ mã nào sử dụng các bẫy dtrace thích hợp). – astletron

+0

Đây thực sự là một câu trả lời tuyệt vời. Đừng quên chấp nhận nó (mặc dù bạn đã tự trả lời)! – Dan

4

Không có cách nào để thực hiện việc này và thực hiện nó theo từng tiểu cơ sở không phải lúc nào cũng là cách tốt nhất để kiểm tra mức sử dụng bộ nhớ. Tôi sẽ giới thiệu một bộ công cụ mà bạn có thể sử dụng, một số công việc trên toàn bộ chương trình, một số khác cho phép bạn kiểm tra một phần của mã của bạn hoặc một biến duy nhất.

Bạn có thể muốn xem xét sử dụng Valgrind. Thậm chí có một mô-đun Perl được gọi là Test::Valgrind sẽ giúp thiết lập tệp ngăn chặn cho bản dựng Perl của bạn và sau đó kiểm tra rò rỉ bộ nhớ hoặc lỗi trong tập lệnh của bạn.

Ngoài ra còn có Devel::Sizechính xác những gì bạn đã yêu cầu, nhưng trên cơ sở từng biến thay vì theo từng căn cứ.

Bạn có thể sử dụng Devel::Cycle để tìm kiếm tham chiếu bộ nhớ vô ý tròn trong cấu trúc dữ liệu phức tạp. Trong khi tham chiếu vòng tròn không có nghĩa là bạn đang lãng phí bộ nhớ khi bạn sử dụng đối tượng, tham chiếu vòng tròn ngăn chặn bất kỳ thứ gì trong chuỗi khỏi bị giải phóng cho đến khi chu trình bị hỏng.

Devel::Leak là một chút phức tạp hơn phần còn lại, nhưng về cơ bản sẽ cho phép bạn nhận thông tin đầy đủ trên bất kỳ SV nào được tạo và không bị hủy giữa hai điểm trong quá trình thực thi chương trình của bạn. Nếu bạn kiểm tra điều này qua một cuộc gọi phụ, bạn sẽ biết bất kỳ bộ nhớ mới nào mà chương trình con được cấp phát.

Bạn cũng có thể muốn đọc phần perldebguts trong hướng dẫn Perl.

Tôi thực sự không thể trợ giúp nhiều hơn vì mọi codebase sẽ có sự khác biệt. Kiểm tra :: Valgrind sẽ làm việc tuyệt vời cho một số codebases và terribly trên những người khác. Nếu bạn đang thử nó, tôi khuyên bạn nên sử dụng phiên bản mới nhất của Valgrind có sẵn và Perl> = 5.10, như Perl 5.8 và Valgrind lịch sử đã không nhận được quá tốt.

+0

Xin chào @Dan. Cảm ơn bạn đã trả lời nhanh. Tôi không nghĩ rằng tôi có một rò rỉ bộ nhớ hoặc tham khảo tuần hoàn. Tôi nghĩ rằng có khả năng ai đó đã khai báo một hashef ở phạm vi gói và nó đang được lấp đầy từ từ khi quá trình này đánh dấu (có thể là một bộ nhớ cache 'được triển khai kém' không có kích thước tối đa). Tìm kiếm một cách tiếp cận sẽ cho phép tôi xác định mã nào của tôi đang gây ra perl để yêu cầu thêm RAM. Đầu ra lý tưởng của tôi sẽ là một danh sách các tên phụ đủ điều kiện với lượng RAM được phân bổ như là một tác dụng phụ của việc thực hiện chúng. Tôi nghĩ rằng tôi có thể nhận được gần với đầu ra này với dtrace. – astletron

2

Bạn có thể muốn nhìn vào Memory::UsageDevel::Size

Để kiểm tra toàn bộ quá trình hoặc phụ:

use Memory::Usage; 
my $mu = Memory::Usage->new(); 

# Record amount of memory used by current process 
$mu->record('starting work'); 

# Do the thing you want to measure 
$object->something_memory_intensive(); 

# Record amount in use afterwards 
$mu->record('after something_memory_intensive()'); 

# Spit out a report 
$mu->dump(); 

Hoặc để kiểm tra các biến cụ thể:

use Devel::Size qw(size total_size); 

my $size = size("A string"); 

my @foo = (1, 2, 3, 4, 5); 
my $other_size = size(\@foo); 

my $foo = { 
    a => [1, 2, 3], 
    b => {a => [1, 3, 4]} 
}; 
my $total_size = total_size($foo); 
+0

Heya @Ranguard. Tôi đã hy vọng để tránh một giải pháp đòi hỏi tôi phải thêm nhiều thiết bị vào mã. Dễ dàng bị bắt trong một mã/chạy/phân tích/mã vòng lặp theo cách đó. Có lẽ tôi đang chiến đấu với cối xay gió, nhưng tôi hy vọng sẽ sử dụng dtrace như NYTProf về tiêu thụ bộ nhớ perl - thứ mà tôi có thể chạy để phân tích mã của mình bằng cách thay đổi mã. – astletron

1

Bạn có thể viết một cách đơn giản mô-đun gỡ lỗi dựa trên Devel::CallTrace để in phụ được nhập cũng như kích thước bộ nhớ hiện tại của quy trình hiện tại. (Sử dụng/proc hoặc bất kỳ thứ gì.)

+0

Xin chào @Mithaldu. Đối với phương pháp này, tôi nghĩ rằng tôi muốn ghi lại kích thước quá trình thay đổi từ thời điểm một phụ được nhập vào thời gian phụ còn lại. Chắc chắn xem làm thế nào tôi có thể nhận được 'profiler giống như' đầu ra (với bộ nhớ tăng thay thế thời gian thực hiện) theo cách này. Cảm ơn bạn đã gợi ý hte. Sẽ cung cấp cho nó một đi nếu tiếp cận dựa trên dtrace không chứng minh hiệu quả. – astletron

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