2012-11-13 9 views
5

Tôi đang viết rất nhiều thứ để đăng nhập các cụm và tối ưu hóa đường dẫn dữ liệu. Tôi xây dựng văn bản tường trình với StringBuilder. Điều gì sẽ là năng lực ban đầu hiệu quả nhất, quản lý bộ nhớ khôn ngoan, vì vậy nó sẽ làm việc tốt bất kể JVM? Mục đích là để tránh tái phân bổ hầu như luôn luôn, cần được bao phủ bởi công suất ban đầu khoảng 80-100. Nhưng tôi cũng muốn lãng phí càng ít byte càng tốt, kể từ khi thể hiện StringBuilder có thể treo xung quanh trong bộ đệm và lãng phí các byte tạo ra.Kích thước dung lượng ban đầu hiệu quả nhất cho StringBuilder?

Tôi nhận thấy điều này phụ thuộc vào JVM, nhưng phải có một số giá trị, sẽ lãng phí ít byte nhất, bất kể JVM, loại "mẫu số chung nhỏ nhất". Tôi hiện đang sử dụng 128-16, trong đó 128 là số tròn đẹp, và trừ cho chi phí phân bổ. Ngoài ra, điều này có thể được coi là trường hợp "tối ưu hóa sớm", nhưng vì câu trả lời tôi là sau đây là số "quy tắc-ngón tay cái", biết rằng nó sẽ hữu ích trong tương lai.

Tôi không mong đợi câu trả lời "phỏng đoán tốt nhất của tôi" (câu trả lời của tôi ở trên đã là), tôi hy vọng ai đó đã nghiên cứu điều này và có thể chia sẻ câu trả lời dựa trên tri thức.

+0

Câu trả lời cho câu hỏi này phụ thuộc vào rất nhiều thứ, ví dụ: văn bản bạn lưu trữ trong một chuỗi 'StringBuilder' vv. Cách duy nhất để tìm ra là đo bằng cách sử dụng bộ nhớ và/hoặc cấu hình CPU. Không có lý do gì để lo lắng về một vài byte trừ khi bạn đang tạo hàng trăm nghìn đối tượng 'StringBuilder'. – Jesper

+1

Đến nay chi phí lớn nhất là chi phí của IO. Trừ khi bạn không có ý định ghi dữ liệu này vào IO, tôi sẽ không lo lắng về nó. –

Trả lời

3

Vâng, tôi đã tự mình thử nghiệm bản thân một thời gian ngắn, và sau đó thử nghiệm thêm sau khi nhận xét để nhận câu trả lời được chỉnh sửa này.

Sử dụng JDK 1.7.0_07 và ứng dụng thử nghiệm báo cáo tên VM "Java HotSpot (TM) 64-Bit Server VM", granularity của StringBuilder sử dụng bộ nhớ là 4 chars, tăng tại thậm chí 4 ký tự.

Trả lời: bất kỳ bội số nào trong số 4 đều có dung lượng tốt như nhau đối với StringBuilder từ điểm phân bổ bộ nhớ, ít nhất là trên JVM 64 bit này.

Thử nghiệm bằng cách tạo 1000000 đối tượng StringBuilder với dung lượng ban đầu khác nhau, trong các lần thực hiện chương trình thử nghiệm khác nhau (có cùng trạng thái đống ban đầu) và in ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() trước và sau.

In ra kích thước heap cũng được xác nhận, số tiền thực sự được phân bổ từ heap cho mỗi bộ đệm của StringBuilder là bội số thậm chí là 8 byte, như dự kiến ​​vì Java char dài 2 byte.Nói cách khác, phân bổ 1000000 trường hợp với dung lượng ban đầu 1,.4 mất khoảng 8 megabyte bộ nhớ ít hơn (8 byte cho mỗi instace), hơn phân bổ cùng một số lượng các bản in với công suất ban đầu 5 ... 8.

+0

Bạn có muốn chia sẻ các thủ tục kiểm tra của mình không? - Làm thế nào để bạn quản lý để xác định việc sử dụng đống với mức chi tiết như vậy? – JimmyB

+0

Tôi không có mã tiện dụng, nhưng việc sử dụng đống đã tăng lên mỗi bước tăng lên 4 đơn vị trong dung lượng ban đầu của StringBuilder, sau đó tương tự cho 3 kích thước tiếp theo, trước khi nhảy lên ở bội số tiếp theo của 4 lần nữa. ** Nhưng ** đó là 4 ký tự, có nghĩa là 8 byte, phải không? Cảm ơn bạn đã hỏi, tôi chắc chắn sẽ kiểm tra lại vào ngày mai để xác minh điều này. – hyde

+0

Vì vậy, bạn quan sát thấy sự gia tăng sử dụng đống trong các bước 1000000 x 4 byte? - Tôi không dám nghĩ đến việc ước tính có bao nhiêu byte của vùng lưu trữ Java mà [cấu trúc dữ liệu] sẽ chiếm giữ, không phải cho 'char' và không cho bất kỳ giá trị/kiểu nào khác trong bất kỳ chương trình Java nào. - Bên cạnh đó, không phụ thuộc vào mức độ chi tiết * phân bổ * của vùng heap, độ chi tiết mà tại đó GC quyết định * giải phóng * bộ nhớ quay trở lại heap chưa được biết và sẽ ảnh hưởng đến bất kỳ phép đo nào. - Nếu bạn đang làm thử nghiệm của bạn trong sự tò mò và/hoặc để đo lường một số đặc điểm của một JVM nhất định, hãy tiếp tục. - Nếu không, ... xem câu trả lời của tôi ở trên :) – JimmyB

4

Đừng cố gắng thông minh trong trường hợp này.

Tôi hiện đang sử dụng 128-16, trong đó 128 là số tròn đẹp và trừ cho chi phí phân bổ.

Trong Java, điều này dựa trên các giả định hoàn toàn tùy ý về hoạt động bên trong của JVM. Java không phải là C. Liên kết Byte và các mức tương tự hoàn toàn là không phải là một vấn đề mà lập trình viên có thể hoặc nên cố gắng khai thác.

Nếu bạn biết độ dài tối đa (có thể xảy ra) của chuỗi bạn có thể sử dụng cho kích thước ban đầu. Ngoài ra, mọi nỗ lực tối ưu hóa đơn giản là vô ích.

Nếu bạn thực sự biết rằng một lượng lớn StringBuilder của bạn sẽ được khoảng thời gian rất dài (mà không hoàn toàn phù hợp với các khái niệm về khai thác gỗ), bạn thực sự cảm thấy cần phải cố gắng thuyết phục các JVM để tiết kiệm một số byte của không gian heap bạn có thể thử và sử dụng trimToSize() sau khi chuỗi được xây dựng hoàn toàn. Nhưng, một lần nữa, miễn là dây của bạn không lãng phí megabyte mỗi bạn thực sự nên đi và tập trung vào các vấn đề khác trong ứng dụng của bạn.