2016-09-15 16 views
12

Tôi có một ứng dụng đọc dữ liệu văn bản khổng lồ thành một kích thước vô hướng, đôi khi thậm chí là GB. Tôi sử dụng substr trên vô hướng đó để đọc hầu hết dữ liệu vào vô hướng khác và thay thế dữ liệu được trích xuất bằng một chuỗi rỗng, bởi vì nó không cần thiết trong vô hướng đầu tiên nữa. Những gì tôi đã tìm thấy gần đây là Perl không giải phóng bộ nhớ của vô hướng đầu tiên, trong khi nó nhận ra rằng chiều dài hợp lý của nó đã thay đổi. Vì vậy, những gì tôi cần làm là trích xuất dữ liệu từ vô hướng đầu tiên thành thứ ba một lần nữa, undef vô hướng đầu tiên und đặt dữ liệu được trích xuất trở lại tại chỗ. Chỉ có cách này bộ nhớ bị chiếm bởi vô hướng đầu tiên thực sự được giải phóng. Gán undef cho vô hướng đó hoặc một số giá trị khác nhỏ hơn khối được cấp phát bộ nhớ không thay đổi bất cứ điều gì về bộ nhớ được cấp phát.Perl: Khi nào bộ nhớ không cần thiết của một vô hướng giải phóng mà không đi ra khỏi phạm vi?

Sau đây là những gì tôi làm bây giờ:

 $$extFileBufferRef = substr($$contentRef, $offset, $length, ''); 
    $length   = length($$contentRef); 
    my $content   = substr($$contentRef, 0, $length); 
    $$contentRef  = undef($$contentRef) || $content; 

$$contentRef có thể là ví dụ Kích cỡ 5 GB trong dòng đầu tiên, tôi trích xuất 4,9 GB dữ liệu và thay thế dữ liệu được trích xuất. Dòng thứ hai giờ đây sẽ báo cáo ví dụ: 100 MB dữ liệu dưới dạng chiều dài của chuỗi, nhưng ví dụ: Devel::Size::total_size vẫn sẽ xuất 5 GB dữ liệu được phân bổ cho vô hướng đó. Và chỉ định undef hoặc chẳng hạn như $$contentRef dường như không thay đổi một điều gì về điều đó, tôi cần gọi undef làm chức năng trên vô hướng đó.

Tôi đã dự kiến ​​rằng bộ nhớ đằng sau $$contentRef đã được giải phóng ít nhất một phần sau khi substr được áp dụng. Dường như không phải là trường hợp ...

Vì vậy, bộ nhớ chỉ được giải phóng nếu các biến nằm ngoài phạm vi? Và nếu có, tại sao chỉ định undef khác nhau để gọi undef làm hàm trên cùng một vô hướng?

+3

Bạn có cần ** bộ nhớ đó ở nơi khác không? – simbabque

+0

Có, tôi có nhiều bản sao của dữ liệu xung quanh vì các lý do khác nhau và bổ sung toàn bộ quá trình có thể được thực hiện song song. Vì vậy, một số GB bộ nhớ bị lãng phí trong toàn bộ quá trình là điều tôi cần quan tâm. Và có, có thể là thiết kế xấu và tất cả, nhưng đó là cách nó hiện đang ... –

Trả lời

13

Phân tích của bạn là chính xác.

$ perl -MDevel::Peek -e' 
    my $x; $x .= "x" for 1..100; 
    Dump($x); 
    substr($x, 50, length($x), ""); 
    Dump($x); 
' 
SV = PV(0x24208e0) at 0x243d550 
    ... 
    CUR = 100  # length($x) == 100 
    LEN = 120  # 120 bytes are allocated for the string buffer. 

SV = PV(0x24208e0) at 0x243d550 
    ... 
    CUR = 50  # length($x) == 50 
    LEN = 120  # 120 bytes are allocated for the string buffer. 

Perl không chỉ phân bổ chuỗi, thay vì sử dụng lại lần sau khi phạm vi được nhập.

$ perl -MDevel::Peek -e' 
    sub f { 
     my ($set) = @_; 
     my $x; 
     if ($set) { $x = "abc"; $x .= "def"; } 
     Dump($x); 
    } 

    f(1); 
    f(0); 
' 
SV = PV(0x3be74b0) at 0x3c04228 # PV: Scalar may contain a string 
    REFCNT = 1 
    FLAGS = (POK,pPOK)    # POK: Scalar contains a string 
    PV = 0x3c0c6a0 "abcdef"\0  # The string buffer 
    CUR = 6 
    LEN = 10      # Allocated size of the string buffer 

SV = PV(0x3be74b0) at 0x3c04228 # Could be a different scalar at the same address, 
    REFCNT = 1      # but it's truly the same scalar 
    FLAGS =()      # No "OK" flags: undef 
    PV = 0x3c0c6a0 "abcdef"\0  # The same string buffer 
    CUR = 6 
    LEN = 10      # Allocated size of the string buffer 

Lý do là nếu bạn cần bộ nhớ một lần, bạn sẽ cần một lần nữa.

Vì lý do tương tự, gán undef cho vô hướng không giải phóng bộ đệm chuỗi của nó. Nhưng Perl cung cấp cho bạn một cơ hội để giải phóng các bộ đệm nếu bạn muốn, do đó, đi qua một vô hướng để undef không lực lượng giải phóng bộ đệm bên trong vô hướng.

$ perl -MDevel::Peek -e' 
    my $x = "abc"; $x .= "def"; Dump($x); 
    $x = undef;     Dump($x); 
    undef $x;     Dump($x); 
' 
SV = PV(0x37d1fb0) at 0x37eec98 # PV: Scalar may contain a string 
    REFCNT = 1 
    FLAGS = (POK,pPOK)    # POK: Scalar contains a string 
    PV = 0x37e8290 "abcdef"\0  # The string buffer 
    CUR = 6 
    LEN = 10      # Allocated size of the string buffer 

SV = PV(0x37d1fb0) at 0x37eec98 # PV: Scalar may contain a string 
    REFCNT = 1 
    FLAGS =()      # No "OK" flags: undef 
    PV = 0x37e8290 "abcdef"\0  # The string buffer is still allcoated 
    CUR = 6 
    LEN = 10      # Allocated size of the string buffer 

SV = PV(0x37d1fb0) at 0x37eec98 # PV: Scalar may contain a string 
    REFCNT = 1 
    FLAGS =()      # No "OK" flags: undef 
    PV = 0       # The string buffer has been freed. 
+0

Cảm ơn, đã không nhận thức được rằng ra khỏi phạm vi hành vi. Đó là cách tiếp cận bộ nhớ đệm cho mỗi trình xử lý hệ điều hành hoặc trình thông dịch Perl? Bởi vì tôi đang sử dụng mod_perl và nhận ra rằng một lượng lớn bộ nhớ được lưu giữ trong quá trình sau khi yêu cầu. Tư tưởng của một rò rỉ bộ nhớ một nơi nào đó, nhưng có thể là "thông minh" bộ nhớ đệm. Một quá trình có thể có nhiều thông dịch viên trong bộ nhớ và nếu tất cả các bộ nhớ cache đó có một số GB dữ liệu thì tôi gặp sự cố. –

+0

Xin lỗi, đừng nghĩ rằng tôi hiểu câu trả lời của bạn: Nhiều chủ đề cho mỗi quá trình chọn tùy ý thông dịch có sẵn trong bộ nhớ trong một hồ bơi trong mod_perl nếu tôi là chính xác.Vì vậy, bộ nhớ đệm/được cấp phát cần phải được gán cho các trình thông dịch và chỉ được sử dụng nếu một số luồng thực thi một số trình thông dịch với bộ nhớ được lưu trữ/cấp phát đó? Các thông dịch viên khác không có lợi, nhưng thay vào đó, hãy phân bổ chúng. Một chủ đề để lại một thông dịch viên không giải phóng bộ nhớ. 10 thông dịch viên, 10 * 2 GB dữ liệu được phân bổ chẳng hạn. Chỉ xóa khi người phiên dịch bị xóa khỏi tiến trình. Đúng? –

+0

mod_perl-thông dịch viên không được giải phóng sau khi sử dụng, họ ở trong bộ nhớ và theo mặc định được sử dụng nhiều lần bởi các chủ đề khác nhau. Khác mod_perl chính nó sẽ không có ý nghĩa bởi vì bạn không đạt được bất kỳ hiệu suất nếu tất cả các thông dịch viên sẽ được giải phóng trực tiếp sau khi yêu cầu. Mã sẽ cần phải được biên dịch hơn và hơn nữa ... Ngay cả các tài liệu nói cách khác: https://perl.apache.org/docs/2.0/user/config/config.html#Threads_Mode_Specific_Directives –

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