2009-07-24 48 views
8

Tôi đọc ở đâu đó rằng java có thể cấp phát bộ nhớ cho các đối tượng trong khoảng 12 lệnh máy. Nó khá ấn tượng đối với tôi. Theo như tôi hiểu một trong những thủ thuật JVM sử dụng là preallocating bộ nhớ trong khối. Điều này giúp giảm thiểu số lượng yêu cầu cho hệ điều hành, điều này khá đắt, tôi đoán vậy. Nhưng ngay cả các hoạt động CAS cũng có thể tốn tới 150 chu kỳ trên các bộ vi xử lý hiện đại.Phân bổ bộ nhớ nonblocking Java

Vì vậy, bất cứ ai có thể giải thích chi phí thực của phân bổ bộ nhớ trong java và các thủ thuật mà JVM sử dụng để tăng tốc độ phân bổ?

+0

Một JVM điển hình sẽ chỉ sử dụng hệ điều hành để bổ sung thêm bộ nhớ để đống. Hầu hết thời gian nó đang tái sử dụng những gì nó đã có. –

Trả lời

17

Các JVM trước phân bổ diện tích bộ nhớ cho mỗi thread (TLA hoặc chủ đề Local Area). Khi một chủ đề cần cấp phát bộ nhớ, nó sẽ sử dụng "Bump phân bổ con trỏ" trong khu vực đó. (Nếu "con trỏ tự do" trỏ tới địa chỉ 10 và đối tượng được phân bổ là kích thước 50, thì chúng tôi chỉ cần di chuyển con trỏ miễn phí đến 60 và cho biết chuỗi có thể sử dụng bộ nhớ từ 10 đến 59 cho đối tượng) .

+0

Cảm ơn rất nhiều. Đó là thứ tôi đang tìm kiếm, nhưng không biết cách hỏi google về nó. :) Nhưng điều thú vị ... Chỉ đề cập đến tôi đã tìm thấy về TLA là trong Oracle JRock JVM (flag -XXtlaSize). Tính năng này có trong Sun JVM không? –

+1

Thuật ngữ Mặt trời là Bộ đệm Phân bổ Địa phương Chủ đề. Các tiêu chuẩn TLA cho bộ đệm dịch Look-Aside (đổ lỗi cho IBM) và đề cập đến các bản đồ bộ nhớ đệm phần cứng. –

+1

Bạn đã đúng, tôi đã tìm thấy thông tin. Cảm ơn. Btw, tôi đoán Bộ đệm dịch Lookaside viết tắt như TLB :) http://en.wikipedia.org/wiki/Translation_lookaside_buffer –

2

Bí quyết tốt nhất là bộ thu gom rác thế hệ. Điều này giữ cho heap không bị phân mảnh, do đó việc cấp phát bộ nhớ sẽ tăng con trỏ tới vùng trống và trả về giá trị cũ. Nếu bộ nhớ hết, các đối tượng sao chép bộ sưu tập rác và tạo theo cách này một đống mới không bị phân mảnh.

Vì các luồng khác nhau phải đồng bộ hóa qua con trỏ tới bộ nhớ trống, nếu tăng nó, chúng sẽ phân chia các khối. Vì vậy, một luồng có thể cấp phát bộ nhớ mới mà không cần khóa.

Tất cả điều này được giải thích chi tiết hơn ở đây: http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

1

Không có bộ cấp phát bộ nhớ duy nhất cho JVM. IIRC chính xác JVM của Sun và bộ nhớ được quản lý của IBM khác nhau. Tuy nhiên nhìn chung cách JVM sẽ hoạt động là ban đầu nó sẽ cấp phát một phần bộ nhớ, phân đoạn này sẽ đủ nhỏ để sống trong bộ nhớ cache của bộ vi xử lý làm cho tất cả các truy cập này cực nhanh.

Khi bạn bên trong ứng dụng tạo đối tượng, đối tượng sẽ lấy bộ nhớ từ bên trong phân khúc này. Việc phân bổ đối tượng trong phân khúc chỉ đơn giản là số học con trỏ.

Ban đầu địa chỉ offset vào phân khúc mới được đúc sẽ bằng không. Đối tượng đầu tiên được phân bổ sẽ có một 'địa chỉ' (thực sự là một bù đắp vào phân đoạn) bằng không. Khi bạn phân bổ đối tượng thì trình quản lý bộ nhớ sẽ biết mức độ lớn của đối tượng, phân bổ nhiều khoảng trống trong phân đoạn (16 byte nói) và sau đó tăng "địa chỉ offset" bằng số tiền đó có nghĩa là cấp phát bộ nhớ nhanh chóng, nó chỉ là con trỏ số học.

Sun có một whitepaper đây http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf và IBM đã từng có một loạt các công cụ trên ibm.com/developerworks

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