Do ngoại lệ có vẻ quá sớm, chúng tôi đã kiểm tra chặt chẽ việc sử dụng bộ nhớ của các cấu trúc .NET khác nhau ... đặc biệt là các đối tượng lớn có xu hướng phân mảnh Heap đối tượng lớn, gây ra ngoại lệ sớm trong bộ nhớ. Một khu vực đáng ngạc nhiên là các lớp .NET Image: Bitmap và Metafile.Việc sử dụng bộ nhớ và phân mảnh các lớp ảnh .NET: Bitmap so với Metafile
Đây là những gì chúng tôi nghĩ rằng chúng tôi đã học được, nhưng đã không thể tìm thấy MS tài liệu để xác minh, vì vậy chúng tôi sẽ đánh giá cao bất kỳ người khác xác nhận có thể cung cấp:
(1) Khi bạn tạo một đối tượng Bitmap từ một raster nén tập tin (JPG, PNG, GIF, vv), nó tiêu thụ bộ nhớ cho một mảng pixel hoàn toàn không nén, ở độ phân giải đầy đủ của tập tin đó. Vì vậy, ví dụ, một JPG 5MB là 9000x3000 pixel sẽ được mở rộng thành 9000x3000x3 byte (giả sử 24 bit màu, không có alpha) hoặc 81MB bộ nhớ được tiêu thụ. Chính xác?
(1a) Có một số bằng chứng (xem 2b bên dưới) rằng C ALNG C storesNG lưu trữ định dạng nén gốc ... do đó, trên thực tế 86MB trong trường hợp này. Nhưng điều đó không rõ ... có ai biết không?
(2) Khi bạn tạo đối tượng Metafile và sau đó vẽ một tệp raster (JPG, PNG, GIF, v.v.) vào nó, nó chỉ tiêu thụ bộ nhớ cho tệp nén. Vì vậy, nếu bạn vẽ một JPG 5MB là 9000x3000 pixel vào một Metafile, nó sẽ chỉ tiêu tốn khoảng 5MB bộ nhớ. Chính xác?
(2a) Để vẽ một tệp raster vào đối tượng Metafile, cách duy nhất có vẻ là tải một Bitmap với tệp và sau đó vẽ Bitmap vào siêu tệp. Có cách nào tốt hơn không liên quan đến việc tạm thời tải dữ liệu bitmap khổng lồ đó (và gây ra phân mảnh bộ nhớ liên quan) không?
(2b) Khi bạn vẽ một Bitmap vào một siêu tệp, nó sử dụng định dạng nén có kích thước tương tự như tệp nén gốc. Liệu nó có làm điều đó bằng cách lưu trữ tệp nén gốc trong Bitmap không? Hay nó làm điều đó bằng cách nén lại Bitmap mở rộng bằng cách sử dụng các thiết lập nén ban đầu?
(3) Ban đầu chúng tôi giả định rằng các đối tượng hình ảnh lớn (> 85KB) sẽ được đặt trong Vùng đối tượng lớn. Trong thực tế, điều đó dường như KHÔNG là trường hợp. Thay vào đó, mỗi Bitmap và mỗi Metafile là một đối tượng 24-byte trong Heap đối tượng nhỏ đề cập đến một khối bộ nhớ riêng có chứa dữ liệu thực. Chính xác?
(3a) Giả sử bộ nhớ gốc giống như Heap đối tượng lớn ở chỗ nó không thể nén được ... khi đối tượng lớn được đặt vào bộ nhớ riêng, nó sẽ không bao giờ được di chuyển và do đó phân mảnh bộ nhớ riêng có thể gây ra nhiều vấn đề như sự phân mảnh của Heap đối tượng lớn. Thật? Hay có cách xử lý đặc biệt dữ liệu Bitmap/Metafile cơ bản hiệu quả hơn?
(3b) Vì vậy, có vẻ như có bốn khối bộ nhớ độc lập được quản lý riêng biệt và chạy ra khỏi mỗi bộ nhớ có thể dẫn đến cùng ngoại lệ bộ nhớ ngoài: Small Object Heap (đối tượng được quản lý < 85KB, được nén bởi GC), Large Object Heap (các đối tượng được quản lý> 85KB được thu thập bởi GC, nhưng không được nén), Native Memory (các đối tượng không được quản lý, có lẽ không được nén) và Desktop Heap (nơi các cửa sổ xử lý và các tài nguyên hạn chế được quản lý). Tôi đã ghi lại bốn tài liệu đó đúng chưa? Có những người khác chúng ta nên biết?
Bất kỳ sự rõ ràng nào mà bất kỳ ai có thể cung cấp ở trên đều sẽ được đánh giá cao. Nếu có một cuốn sách hoặc bài viết hay giải thích đầy đủ ở trên, vui lòng cho tôi biết. (Tôi rất vui khi thực hiện việc đọc cần thiết, nhưng phần lớn các cuốn sách không nhận được điều đó sâu sắc, và do đó không cho tôi biết bất cứ điều gì tôi chưa biết.)
Cảm ơn!
GDI + lưu trữ dữ liệu hình ảnh trong bộ nhớ không được quản lý. Vì vậy, không có giả định nào của bạn gần gũi. Quên để vứt bỏ bitmap là một cách nhanh chóng để nhấn OOM. Phân mảnh không gian địa chỉ là một phân đoạn khác, quy trình 32 bit đạt tới 90 MB làm vùng nguy hiểm sau một thời gian. –
"không có giả định nào của bạn gần" ?? Nhưng tất cả những gì bạn nói xung quanh đó là phù hợp với các giả định của tôi ở trên ... vì vậy, không chắc chắn những gì bạn đang nói với tôi. Bạn có nói rằng "Bộ nhớ riêng" khác với "bộ nhớ không được quản lý"? Hoặc bạn có nghĩa là "tất cả các giả định của bạn là gần" ?? –
Ngày 2 (a), tốt nhất tôi đã đưa ra cho đến nay là "Không, nhưng có sorta ...": Tạo một exe riêng biệt mà chỉ cần đọc trong bất kỳ tập tin raster nhất định vào một Bitmap và sau đó mở ra một Metafile mới tập tin trên đĩa và DrawImage của Bitmap đó vào Metafile đó và thoát.Sau đó, trong ứng dụng chính của tôi, khi người dùng chỉ cho tôi một tệp raster, thay vì mở nó và tạo ra phân mảnh bộ nhớ trong ứng dụng chính của tôi, tôi gọi nó .exe để tạo một tệp tạm thời chứa Metafile và sau đó trong ứng dụng chính của tôi đọc trực tiếp tệp đó vào một tệp Metafile. Clunky, nhưng không có tác động bộ nhớ trên ứng dụng chính của tôi. Bất kỳ ý tưởng tốt hơn? –