tags:

views:

198

answers:

6

Our system uses a lot of large Bitmaps (System.Drawing.Bitmap) and sometimes we run out of memory and gets a "Parameter is not valid" error. This makes sense, since it can be difficult to allocate large continuous chunk of memory.

So the question is... If we upgraded the system to 64bit, would this problem go away?

A: 

Some time ago I often experienced exactly this kind of errors when developing with Visual Studio 2008 on a Vista 64-Bit system. So I guess moving to 64Bit may increase the chances to succeed and make the error occur less often, but I would not assume that moving to 64-Bit will heal it entirely.

What helped me out was this link: http://confluence.jetbrains.net/display/ReSharper/OutOfMemoryException+Fix

It is a wrapper that replaces the memory allocation policy, s.t. you tend to get larger continuous memory chunks. Maybe you can use a similar memory allocation policy in your application as well, because this one was supposed to wrap visual studio only.

Simpzon
+3  A: 

If this is a memory allocation problem (due to fragmentation of your large object heap it is quite conceivable that you would have trouble allocating 100MB chunks after 20 or so images have been loaded, even if some of them have subsequently been unloaded), then moving to 64 bit should help - the much larger address space should give the heap plenty of room to work, and thus alleviate the symptoms.

A memory issue should produce an OutOfMemoryException, but it's possible that the bitmap handling code in .net is catching this and effectively converting into an InvalidParameterException. However, there is a possibility that there is another issue relating to the size/format of the images, and it is genuinely an Invalid Parameter.

Jason Williams
I just testet on a 64bit system, and was able to create 6 bitmaps of 20000x20000 pixels each. (~1.5GB pr. image) This is nowhere near possible on the 32 bit system.
LaZe
A: 

There is a limit as to how large a bitmap you can create on e a system.

Check out http://www.efg2.com/Lab/Graphics/VeryLargeBitmap.htm for a program that can show you the system limit.

Perhaps you are hitting that limit.

rep_movsd
A: 

Before allocating these big Bitmaps, you could try calling GC.Collect(). I had exactly this problem recently, and that helped. (My first reaction was also to move to 64-bit, but adding one line of code was a little bit simpler. ;-)

danbystrom
Hi, I actually did that, and it did help... but the problem came back anyway.
LaZe
+1  A: 

In general, when you start playing with huge bitmap in memory you always get this kind of issue. Best way to avoid this is to split your image in an array or something similar so you can create a grid.

From that point on, you only need/have to load on the screen what can be viewed which would save a lot of memory.

I had this happen to me when I decided to create a little games to kill some times.

I decided to create a Maze/Pipe game and the user could choose the number of columns and rows. I decided to limit the image to 10000px by 10000px.

My first try, I had exactly your issue. error after error after error, mostly memory issue.

I decided to do some research on how to do what I wanted and I found the solution.

What I did is I created a dynamic 2d array (I decided to limit it to a maximum of 1000 by 1000) and I just put in them small 10x10 pixel image or whatever the user decide.

When that was done, the issue with memory/loading speed/etc... was simply gone.

memory usage before my fix was easily over a gig, now memory usage of the apps is between 150 and 225 megs ram when you use the limit

if you want to try it, download this and go look in the menu(Maze) and play with the setting: my little games

Fredou
+1  A: 

Depending on how the Bitmap is created, whether it is DDB or a DIB video memory or system memory is used (DDB's use video memory, DIB's system memory). You'll have to use DotNet reflector to determine when each one is created depending on the constructor you are using... For example a DDB is created when you go:

var bmp = new Bitmap(width, height, pixelDepth)

and this can have a size limit of 5000x5000 on a machine with a small video card (i.e. servers where you might be running a webservice), whereas you can find that you can load a 10000x10000 bitmap with

var bmp = new Bitmap(pathToLargeFilename);

I haven't had much luck figuring out how to force creation of DIB in Dotnet (my guess is the easiest way would be manual creation of the Bitmap stucture, manual allocation of the memory, and then somehow casting that as a Bitmap. Or maybe your best bet is to move to an alternate imaging library that doesn't use video memory (there are a quite a few open source ones FreeImage, ImageMagick, Cairo (though you will have to at least get the GTK packages from Mono for it to run)

Kris Erickson
Thanks for the tip. It seems to use GdipCreateBitmapFromScan0, so I guess it uses system memory.
LaZe
That's creating a bitmap from a previous bitmap (Scan0), so however that bitmap was made is where the memory allocated.
Kris Erickson