2009-04-25 33 views
17

Làm thế nào để bạn tối ưu hóa việc sử dụng kích thước heap của một ứng dụng có rất nhiều (triệu) đối tượng tồn tại lâu dài? (Bộ nhớ cache lớn, tải rất nhiều hồ sơ từ một db)Làm thế nào để bạn làm cho bộ nhớ ứng dụng Java của bạn hiệu quả?

  • Sử dụng kiểu dữ liệu đúng
    • Tránh java.lang.String để đại diện cho các kiểu dữ liệu khác
  • Tránh lặp lại đối tượng
    • Sử dụng enums nếu các giá trị được biết trước
    • Sử dụng các nhóm đối tượng
    • String.intern() (tốt ý tưởng?)
  • Load/giữ chỉ các đối tượng bạn cần

Tôi đang tìm kiếm lập trình nói chung hoặc câu trả lời cụ thể Java. Không chuyển đổi trình biên dịch sôi nổi.

Chỉnh sửa:

Tối ưu hóa biểu diễn bộ nhớ của POJO có thể xuất hiện hàng triệu lần trong heap.

Sử dụng trường hợp

  • tải một tập tin csv khổng lồ trong bộ nhớ (chuyển đổi thành các POJO)
  • Sử dụng chế độ ngủ đông để lấy triệu hồ sơ từ một cơ sở dữ liệu

Tiếp tục câu trả lời:

  • Sử dụng mẫu cân bằng
  • Sao chép vào ghi
  • Thay vì tải 10M đối tượng có 3 thuộc tính, có hiệu quả hơn khi có 3 mảng (hoặc cấu trúc dữ liệu khác) có kích thước 10M không? (Có thể là một nỗi đau để thao tác dữ liệu nhưng nếu bạn thực sự thiếu bộ nhớ ...)
+9

bằng cách viết chương trình của bạn trong lắp ráp ... :) –

+2

tôi nghi ngờ rằng lắp ráp sẽ giúp - thời gian phát triển sẽ còn đáng kể và sẽ không có nền tảng chéo. ;) – Fortyrunner

+3

@Fortyrunner Tôi nghi ngờ Desmond đang nói đùa. –

Trả lời

17

Bạn không nói loại đối tượng bạn đang tìm cách lưu trữ, do đó rất khó để cung cấp chi tiết khuyên bảo. Tuy nhiên một số phương pháp tiếp cận (không độc quyền), không theo thứ tự đặc biệt, bao gồm:

  • Sử dụng một flyweight pattern bất cứ nơi nào càng tốt.
  • Lưu vào bộ nhớ đệm. Có numerous giải pháp bộ nhớ cache cho Java.
  • Có một số cuộc tranh luận về việc liệu String.intern là một ý tưởng hay. Xem here để biết câu hỏi. String.intern() và số tiền tranh luận về tính phù hợp của nó.
  • Sử dụng tài liệu soft hoặc weak để lưu trữ dữ liệu mà bạn có thể tạo lại/tải lại theo yêu cầu.Xem here để biết cách sử dụng các tham chiếu mềm với các kỹ thuật lưu trong bộ nhớ cache.

Biết thêm về nội bộ và tuổi thọ của các đối tượng bạn đang lưu trữ sẽ dẫn đến câu trả lời chi tiết hơn.

+0

Đã bỏ phiếu tại sao? –

20

Tôi đề nghị bạn sử dụng một bộ nhớ hồ sơ, xem nơi bộ nhớ đang được tiêu thụ và tối ưu hóa điều đó. Nếu không có thông tin định lượng, bạn có thể kết thúc việc thay đổi điều mà không có tác dụng hoặc thực sự làm mọi việc tồi tệ hơn.

Bạn có thể xem xét thay đổi cách trình bày dữ liệu của mình, đặc biệt nếu đối tượng của bạn nhỏ. Ví dụ: Ví dụ, bạn có thể biểu diễn một bảng dữ liệu dưới dạng một loạt các cột với các mảng đối tượng cho mỗi cột, thay vì một đối tượng trên mỗi hàng. Điều này có thể tiết kiệm một lượng đáng kể chi phí cho mỗi đối tượng nếu bạn không cần phải đại diện cho một hàng riêng lẻ. ví dụ. một bảng có 12 cột và 10.000.000 hàng có thể sử dụng 12 đối tượng (một cột cho mỗi cột) thay vì 10 triệu (mỗi cột)

+0

Bí quyết tốt để giảm thiểu số lượng đối tượng. – Boune

+1

Tôi đồng ý rằng một bộ nhớ hồ sơ là một điểm khởi đầu tốt cho một người không biết những trường hợp lớp nào đang dùng hết bộ nhớ. Câu hỏi là nhiều hơn, nếu tôi biết trước tôi sẽ có 10M pojo # 1 trong bộ nhớ, làm thế nào để giảm thiểu mức tiêu thụ của từng trường hợp? – Boune

11

Đảm bảo bình thường hóa mô hình đối tượng của bạn, không trùng lặp giá trị.

Ahem, và nếu nó chỉ hàng triệu đối tượng Tôi nghĩ rằng tôi chỉ muốn đi cho một phong nha 64 bit VM và rất nhiều ram;)

+1

Đó là giải pháp hiệu quả nhất về chi phí :-) –

+0

+1 - Đó là nguyên nhân gây ra vấn đề. – duffymo

+0

Câu trả lời hay. Sử dụng cache của dữ liệu và giảm các bản ghi và trường trùng lặp là một trình tiết kiệm lớn. – Fortyrunner

1

Tôi muốn thêm một cái gì đó đến mức Peter alredy thực hiện (có thể 't bình luận về câu trả lời của mình :() nó luôn luôn tốt hơn để sử dụng một bộ nhớ profiler (kiểm tra java memory profiler) hơn để đi bởi intution.80% thời gian nó thường xuyên mà chúng tôi bỏ qua có một số vấn đề trong nó.

4

Bình thường "profilers" sẽ không giúp bạn nhiều, bởi vì bạn cần một cái nhìn tổng quan của tất cả các đối tượng "sống" của bạn.Bạn cần phân tích đống phân tích. Tôi khuyên bạn nên Eclipse Memory analyzer.

Kiểm tra đối tượng trùng lặp, bắt đầu bằng Chuỗi. Kiểm tra xem bạn có thể áp dụng các mẫu như flightweight, copyonwrite, khởi tạo lười biếng (google sẽ là bạn của bạn) hay không.

2

Bạn chỉ có thể lưu trữ ít đối tượng hơn trong bộ nhớ. :) Sử dụng một bộ nhớ đệm tràn vào đĩa hoặc sử dụng Terracotta để cụm đống của bạn (đó là ảo) cho phép các bộ phận không sử dụng được xả ra khỏi bộ nhớ và minh bạch bị lỗi trở lại.

0

Một ưa thích: giữ hầu hết dữ liệu nén trong ram . Chỉ mở rộng bộ làm việc hiện tại. Nếu dữ liệu của bạn có địa phương tốt có thể hoạt động tốt.

Sử dụng cấu trúc dữ liệu tốt hơn. Các bộ sưu tập tiêu chuẩn trong java là khá bộ nhớ chuyên sâu.

[những gì là một cấu trúc dữ liệu tốt hơn]

  • Nếu bạn có một cái nhìn tại nguồn cho các bộ sưu tập, bạn sẽ thấy rằng nếu bạn hạn chế bản thân trong cách bạn truy cập vào bộ sưu tập, bạn có thể tiết kiệm không gian cho mỗi phần tử.
  • Cách bộ sưu tập xử lý ngày càng tăng là không tốt cho các bộ sưu tập lớn. Quá nhiều sao chép. Đối với các bộ sưu tập lớn, bạn cần một số thuật toán dựa trên khối, như btree.
+0

Bạn định nghĩa cấu trúc dữ liệu tốt hơn như thế nào? Làm thế nào bạn sẽ thực hiện điều đó? – Boune

0

Dành thời gian làm quen và điều chỉnh VM command line options, đặc biệt là những người liên quan đến thu gom rác. Trong khi điều này sẽ không thay đổi bộ nhớ được sử dụng bởi các đối tượng của bạn, nó có thể có tác động lớn đến hiệu suất với các ứng dụng bộ nhớ chuyên sâu trên các máy có nhiều RAM.

1

Nếu bạn có hàng triệu Số nguyên và Số nguyên, v.v. thì hãy xem liệu thuật toán của bạn có cho phép biểu diễn dữ liệu trong mảng nguyên thủy hay không. Điều đó có nghĩa là ít tài liệu tham khảo hơn và chi phí CPU thấp hơn của mỗi bộ sưu tập rác.

0
  1. Assign null giá trị cho tất cả variables được sử dụng no longer. Do đó make it available for Garbage collection.
  2. De-reference the collections khi quá trình sử dụng kết thúc, nếu không GC sẽ không quét chúng.
+1

Tôi không đồng ý với mục 1. Tôi sẽ chỉ cho phép gc làm những gì nó là giả sử để làm. Chỉ có một vài trường hợp (mảng, bộ sưu tập), điều này có thể hữu ích, không phải tất cả các biến. http://stackoverflow.com/questions/449409/does-assigning-objects-to-null-in-java-impact-garbage-collection – Boune

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