2015-10-03 17 views
20

Tôi đang cố gắng hiểu khi nào bộ nhớ được cấp phát từ vùng heap của Ruby được trả về hệ điều hành. Tôi hiểu rằng Ruby không bao giờ trả về bộ nhớ được cấp phát cho nó nhưng tôi vẫn không chắc về hành vi của bộ nhớ heap. tức là những đối tượng không phù hợp với RVALUE 40 byte.Tại sao chương trình Ruby này không trả lại bộ nhớ heap cho hệ điều hành?

Hãy xem xét chương trình sau phân bổ một số chuỗi lớn và sau đó buộc một GC chính.

require 'objspace' 

STRING_SIZE = 250 

def print_stats(msg) 
    puts '-------------------' 
    puts msg 
    puts '-------------------' 
    puts "RSS: #{`ps -eo rss,pid | grep #{Process.pid} | grep -v grep | awk '{ print $1,"KB";}'`}" 
    puts "HEAP SIZE: #{(GC.stat[:heap_sorted_length] * 408 * 40)/1024} KB" 
    puts "SIZE OF ALL OBJECTS: #{ObjectSpace.memsize_of_all/1024} KB" 
end 

def run 
    print_stats('START WORK') 
    @data=[] 
    600_000.times do 
    @data << " " * STRING_SIZE 
    end 
    print_stats('END WORK') 
    @data=nil 
end 

run 
GC.start 
print_stats('AFTER FORCED MAJOR GC') 

Chạy chương trình này với Ruby 2.2.3 trên MRI nó tạo ra kết quả sau. Sau khi GC chính bị ép buộc, kích thước heap như mong đợi nhưng RSS không giảm đáng kể.

------------------- 
START WORK 
------------------- 
RSS: 7036 KB 
HEAP SIZE: 1195 KB 
SIZE OF ALL OBJECTS: 3172 KB 
------------------- 
END WORK 
------------------- 
RSS: 205660 KB 
HEAP SIZE: 35046 KB 
SIZE OF ALL OBJECTS: 178423 KB 
------------------- 
AFTER FORCED MAJOR GC 
------------------- 
RSS: 164492 KB 
HEAP SIZE: 35046 KB 
SIZE OF ALL OBJECTS: 2484 KB 

So sánh các kết quả này với kết quả sau khi chúng tôi phân bổ một đối tượng lớn thay vì nhiều đối tượng nhỏ hơn.

def run 
    print_stats('START WORK') 
    @data = " " * STRING_SIZE * 600_000 
    print_stats('END WORK') 
    @data=nil 
end 

------------------- 
START WORK 
------------------- 
RSS: 7072 KB 
HEAP SIZE: 1195 KB 
SIZE OF ALL OBJECTS: 3170 KB 
------------------- 
END WORK 
------------------- 
RSS: 153584 KB 
HEAP SIZE: 1195 KB 
SIZE OF ALL OBJECTS: 149064 KB 
------------------- 
AFTER FORCED MAJOR GC 
------------------- 
RSS: 7096 KB 
HEAP SIZE: 1195 KB 
SIZE OF ALL OBJECTS: 2483 KB 

Lưu ý giá trị RSS cuối cùng. Chúng tôi dường như đã giải phóng tất cả bộ nhớ mà chúng tôi đã phân bổ cho chuỗi lớn.

Tôi không chắc chắn lý do tại sao ví dụ thứ hai giải phóng bộ nhớ nhưng ví dụ đầu tiên không phải vì chúng đều cấp phát bộ nhớ ngoài vùng heap của Ruby. Đây là một trong số reference có thể cung cấp giải thích nhưng tôi sẽ quan tâm đến những lời giải thích từ người khác.

Việc giải phóng bộ nhớ cho hạt nhân cũng có chi phí. Bộ nhớ không gian người dùng người cấp phát có thể giữ bộ nhớ đó (riêng tư) với hy vọng có thể là được sử dụng lại trong cùng một quy trình và không đưa lại cho hạt nhân để sử dụng trong các quy trình khác.

+1

Đăng ký vào chủ đề này. Tôi cũng rất quan tâm đến điều này. – dimitarvp

+1

Sự khác biệt cơ bản là trong ví dụ thứ nhất, trong đó các đối tượng * mới * 600k được tạo, chỉ trong đối tượng thứ hai. Mặc dù tổng kích thước của dữ liệu * tham chiếu * là giống nhau, ví dụ đầu tiên yêu cầu các vị trí tham chiếu nhiều hơn 600 nghìn lần (có thể là không bao giờ hoặc sau này được khai thác lại cho hệ điều hành). – joanbm

+2

Tôi khuyên bạn nên theo dõi [bài viết] (http://www.sitepoint.com/ruby-uses-memory/) và [giải thích] được liên kết (http://rocket-science.ru/hacking/2013/12/17/ruby-memory-cạm bẫy /) của 'RVALUE's. Tôi không chắc liệu họ có đúng hay không, chỉ có Koichi mà Ko1 có thể biết. Hoặc một số người đam mê quyết tâm mạnh mẽ, phân tích các nguồn Ruby. – joanbm

Trả lời

1

@joanbm có điểm rất tốt ở đây. Đã tham chiếu article explains this pretty well:

GC của Ruby phát hành bộ nhớ dần dần, vì vậy khi bạn thực hiện GC trên 1 bộ nhớ lớn chỉ bằng 1 tham chiếu, nó sẽ giải phóng tất cả, nhưng khi có nhiều tham chiếu, GC sẽ giải phóng bộ nhớ trong chuncks.

Một số cuộc gọi tới GC.start sẽ phát hành nhiều bộ nhớ hơn trong ví dụ thứ nhất.


Dưới đây là 2 bài báo tin tức khác để đào sâu hơn:

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