JonaGik
JonaGik

Reputation: 1573

BitmapImages using ENORMOUS amounts of memory

I have an application which reads JPEGs from an XML file (to byte arrays), generates MemoryStreams and uses these to instantiate BitmapImages. The entire size of the JPEGs is around 60 MB. However, the memory usage for my application is 1.6GB (after which a system out of memory exception occurs).

I retain the byte arrays, MemoryStreams, and (of course) the BitmapImages in memory. I would therefore expect to get around three (maybe more) times the original size stored in memory but 1.6GB is absurd.

What might be causing this?

Thanks in advance for your help.

Upvotes: 2

Views: 163

Answers (1)

KeithS
KeithS

Reputation: 71573

Not that absurd, really. A good rule of thumb to keep in mind is that a JPEG, on average, is about 10% of the size of the same image saved as a BMP. There are some images that are more compressible, some that are less, and the quality and compression settings of the JPEG encoder make a significant difference, but in my experience this tenet usually holds.

If we accept the rule as true in this case, then you program is storing at least 720MB of image data alone; the 60MB of JPEG data in the byte arrays and again in the MemoryStreams, and then 600MB of uncompressed BMP images. In addition, the program also loads itself and any referenced third-party binaries into that same memory space (including DLLs for referenced Framework namespaces; people often forget that the Framework isn't "free" to use just because it's "built-in"), and keep in mind that certain collections request memory for themselves in a very optimistic manner; every time you reach the internal maximum capacity of a List, for instance, it resizes itself to double its previous size. Dictionaries do the same, with the added overhead of maintaining two internal array structures; one for the key hashes, the other for the "nodes" containing actual values which are linked to the key hashes. This behavior can very easily cause a program that deals with collections of a lot of objects to request more memory than the runtime is allowed to provide. Then, if this is a graphical application, the runtime maintains a message loop for each thread working with graphical elements, and hooks to each and every graphical element (each "window", though that term is a misnomer as virtually all GUI elements are "windows", not just the Form objects you'd normally call windows).

All of this can EASILY make an application require 1.6GB of managed memory. Then, when the application asks for either 400MB more memory (to resize a large collection), or for a new handle in excess of 2.1 billion (.NET uses 32-bit indexing even in a 64-bit OS, so the runtime can only keep track of 232 different memory addresses in total per process), the runtime will inject an OOME.

Upvotes: 2

Related Questions