2013-05-24 33 views
13

Nếu tôi có một tập tin XML đó là xung quanh 2kB trên đĩa và tải các nội dung như là một String vào bộ nhớ trong Java và sau đó đo kích thước đối tượng đó là xung quanh 33kB.
File trong kích thước bộ nhớ trong Java

Tại sao kích thước tăng lớn?
Nếu tôi làm điều tương tự trong C++, đối tượng chuỗi kết quả trong bộ nhớ gần gũi hơn với 2kB.

Để đo bộ nhớ trong Java, tôi đang sử dụng Instrumentation. Đối với C++, tôi lấy độ dài của đối tượng được tuần tự hóa (ví dụ: chuỗi).

+11

How are you đo kích thước bộ nhớ? – Ren

+0

Làm thế nào để bạn lưu trữ nó trong bộ nhớ trong java. Ngoài ra Java có một chi phí khoảng 16 byte cho mỗi đối tượng, vì vậy nếu bạn có rất nhiều đối tượng chuỗi nhỏ, bạn sẽ có một chi phí rất cao !!! –

+0

Tôi mong đợi và chi phí, nhưng không ~ 30kB – imrichardcole

Trả lời

1

Trong đối tượng Chuỗi Java có một số dữ liệu bổ sung, làm tăng kích thước của nó.
Đó là dữ liệu đối tượng, dữ liệu mảng và một số biến khác. Đây có thể là tham chiếu mảng, độ lệch, chiều dài, v.v.

Hãy truy cập http://www.javamex.com/tutorials/memory/string_memory_usage.shtml để biết chi tiết.

+0

Tuy nhiên, dữ liệu bổ sung này sẽ không tốn gần 30KB cho chuỗi 2KB (bằng ASCII)/4KB (bằng UTF-16) –

+0

Adrian, bạn nói đúng. Đó là một sai lầm khi nói như vậy. Bạn có thể dễ dàng có các cấu trúc dữ liệu khổng lồ, lưu trữ 0 dữ liệu hữu ích. – Val

+0

java.lang.String chứa tham chiếu đến mảng, độ lệch, độ dài và mã băm dưới dạng số nguyên và 2 tham chiếu khác. Nó sẽ phát ra 24 byte cho x86 jvm và 36b cho x64. Ngoài ra, có một số chi phí bộ nhớ cho mảng char. – Chechulin

3

Tôi nghĩ có nhiều yếu tố liên quan. Trước hết, như Bruce Martin đã nói, các đối tượng trong java có phí trên 16 byte cho mỗi đối tượng, C++ thì không. Thứ hai, các chuỗi trong Java có thể là 2 Byte cho mỗi ký tự thay vì 1. Thứ ba, có thể là Java dự trữ nhiều bộ nhớ hơn cho chuỗi của nó so với chuỗi C++ std :: string.

Xin lưu ý rằng đây chỉ là những ý tưởng có thể có sự khác biệt lớn.

+0

Tôi tin rằng tất cả chúng ta đều biết những chi phí này. Tuy nhiên, nó phải là khoảng gấp đôi chiều dài chuỗi (hoặc x3/x4 nếu có rất nhiều ký tự yêu cầu thay thế). Tuy nhiên nó không thể giải thích sự khác biệt> 15x.Có điều gì khác sai –

+0

Tôi tin rằng những chi phí này khuếch đại bản thân nếu triển khai java sử dụng nhiều đối tượng chuỗi đơn để lưu trữ dữ liệu của nó. – Marius

3

Giả sử tệp XML của bạn chứa các ký tự ASCII và sử dụng mã hóa đại diện cho chúng dưới dạng byte đơn, sau đó bạn có thể kích hoạt kích thước bộ nhớ ít nhất gấp đôi, vì Java sử dụng UTF-16 trong nội bộ (tôi đã nghe của một số JVM cố gắng tối ưu hóa điều này, thouhg). Thêm vào đó sẽ là chi phí cho 2 đối tượng (thể hiện String và mảng char nội bộ) với một số trường, IIRC khoảng 40 byte tổng thể.

Vì vậy, "kích thước đối tượng" của bạn là 33kb chắc chắn là không chính xác, trừ khi bạn đang sử dụng một JVM lạ. Phải có một số vấn đề với phương pháp bạn sử dụng để đo lường nó.

+0

Yep, kích thước đối tượng phải được làm tròn thành 8 IIRC. – Chechulin

+0

@michael - hãy để tôi kiểm tra việc thực hiện đo kích thước – imrichardcole

0

Có, bạn nên GC và dành thời gian để hoàn thành. Chỉ cần System.gc(); và in totalMem() trong vòng lặp. Bạn cũng tốt hơn để tạo một triệu bản sao chuỗi trong mảng (đo kích thước mảng trống và, sau đó, đầy chuỗi), để chắc chắn rằng bạn đo kích thước của chuỗi chứ không phải các đối tượng dịch vụ khác, có thể có trong chương trình của bạn. Chỉ riêng chuỗi không thể mất 32 kb. Tuy nhiên, việc xếp hạng các đối tượng XML có thể.

Nói rằng, tôi không thể chống lại sự trớ trêu rằng không ai quan tâm đến bộ nhớ (và truy cập bộ nhớ cache) trong thế giới Java. Chúng tôi biết rằng JIT đang cải thiện và nó có thể hoạt động tốt hơn mã C++ gốc trong một số trường hợp. Vì vậy, không cần phải bận tâm về tối ưu hóa bộ nhớ. Tối ưu hóa sơ bộ là gốc rễ của tất cả các tệ nạn.

+0

JIT có thể là điểm hợp lệ. Chỉ cần tò mò, trong trường hợp nào JIT có thể nghĩ rằng việc tạo ra một mảng lớn có thể mang lại lợi ích cho ứng dụng? –

+0

Ai đã nói với bạn về mảng lớn? Tôi biết rằng JVM thích rất nhiều đối tượng nhỏ, mỗi tiêu thụ rất nhiều bộ nhớ. – Val

+0

arrr ... Tôi đã chỉ nghĩ rằng JIT mảnh duy nhất có thể "tối ưu hóa" trên đối tượng String để làm cho nó phát triển quá lớn là mảng char trong đó. Có lẽ tôi nên hỏi, "Chỉ cần tò mò, trong trường hợp nào JIT có thể nghĩ rằng phân bổ một mảnh lớn hơn nhiều bộ nhớ cho một đối tượng nhỏ có thể có lợi cho ứng dụng?" –

1

Chuỗi: Tăng trưởng bộ nhớ của chuỗi theo dõi sự tăng trưởng mảng nội bộ của mảng. Tuy nhiên, lớp chuỗi thêm 24 byte phí khác. Đối với chuỗi không có kích thước 10 ký tự trở xuống, chi phí bổ sung trên không liên quan đến tải trọng hữu ích (2 byte cho mỗi char cộng với 4 byte cho chiều dài), dao động từ 100 đến 400 phần trăm.

thêm: What is the memory consumption of an object in Java?

0

Như đã nêu trong câu trả lời khác, Java String được thêm một chi phí. Nếu bạn cần lưu trữ một số lượng lớn các chuỗi trong bộ nhớ, tôi khuyên bạn nên lưu trữ chúng dưới dạng byte [] thay thế. Làm như vậy kích thước trong bộ nhớ phải giống với kích thước trên đĩa.

String -> byte []:

String a = "hello"; 
byte[] aBytes = a.getBytes(); 

byte [] -> String:

String b = new String(aBytes); 
Các vấn đề liên quan