I have an app running on the debugger. Seems to be doing fine but I’m getting the following message periodically. I suspect it’s not good but it’s not apparent what’s happening. How do I debug this?
that is telling you that the memory allocation is failing, and forcing GC to run. Perhaps once GC runs your failures are no longer a problem, but this just means you’re running low on memory. Have you turned off GC diagnostics ? I’d suggest you turn that on and see how memory usage is changing in your app over time, and I’d also be focussing in on what is triggering the failed allocation and check you don’t have some memory leak in your code that GC is cleaning up (That might bite you later)
What it seems to me is that the GC is cleaning up unused objects and increasing available space - you go from 31k down to 26k used when the GC runs. The other thing GC does is make space contiguous, and depending what you were allocating it’s likely that needed to be contiguous.
I’ve figured out that the message occurs when I am create a PersistentStorage object, mount the SD file system and open a small text file on an SD card on a Fez Panda II. I can imagine that takes some dynamic memory space but I don’t see what I can do about it.
Is the “allocation failure” a problem is just some kind of warning that there could be a problem?
The FREEBLOCK is 38K bytes which sounds like plenty of free memory to me but maybe I’m misinterpreting the numbers. In the line below is the 26148 bytes used coming out of 38232 total bytes available or is the 38232 what’s available over and above the 26148 used?
OK. I now call Debug.GC(true) just before dealing with the file and that appears to have stopped the message.
I still don’t understand if it was just an informational message or something to be concerned about. It seems that when the message occurred it ran GC for me so there wasn’t any negative consequence.
Also how much memory do I have to spare - 38K or 38K- 26K?
The message is “informational” in that the allocation actually worked, but it had a consequence. Because of the failed allocation, GC was forced (costs you a few msec or more of time) and then the allocation succeeded and your app continued. Your failure wasn’t because of lack of memory but because of fragmented available memory.
This is something you need to worry about, but at the same time you don’t need to worry. As you can see, GC deals with this specific situation well and you continue happily afterwards, but if you were running on very tight timing you may find the GC delay is impacting you. It’s likely that your file handling code is the cause of this issue and a small change could potentially remove the GC - if you want to look deeper, you’ll need to share code, but as a first pointer, if you search the forum for USING statements and file handling you’ll find similar threads that talk about the disposal of file objects.
To answer your memory available question: you have 26k of memory that is used by your data, and you have 38k available.
Thank you Brett. I will continue to explore this topic as time permits. I don’t mean to be a pain but I would appreciate one more clarification.
In your answer you say “To answer your memory available question: you have 26k of memory that is used by your data, and you have 38k available.” but I would like to be clear that the 38K available is in addition to the memory used - the 26K - meaning that I have a total amount of memory (used and available) on the order of 64K. Is that correct?
Yes I did figure out that I clearly had that much RAM. I’m getting ready to work some more on the SD card file I/O again and I hope to figure out why with >30K of RAM I had an allocation failure. Off hand do you know if there is any way I can check in SW the size of the FREEBLOCK? I’ve been watching the GC output after I perform certain functions which is a bit tedious and uncertain.
Debug.Print("Free mem : " + Debug.GC(false).ToString())
will help you.
To me it seems like you have lingering storage handles. USING will dispose of them quicker, but still may not give you the “ideal” scenario, but forcing GC to run (Debug.GC(true)) before you open a new handle may help.
@ sa319 - I’ve noticed the following issues on the Panda II:
[ul]Even when GC reports > 18K available it sometimes can’t allocate 6K. Problably because it needs a contiguous block of 6K, which isn’t available?
FileStream constructor, File.Open, and StreamReader constructor all use 8K+ of RAM, and don’t seem to give all of it back even if I force GC to run. I’ve read about some memory leaks in these stream classes in 4.1 that were fixed in 4.2?
Running GC(true) too often, seems to have the opposite affect than intended. This is when I’m running under the debugger, which may interact in some funny way?
Sometimes doing a Thread.Sleep(100) after something is closed/disposed and after GC(true) is run seems to help?[/ul]
Jasdev has much more experience than I do in these things, so his comments are very valid. Yes you need about 8k contiguous memory for filestream, that’s confirmed and if you’re low (~18K from Jasdev’s experience) you may run into the situation where you can’t write the file. Whether there’s bug fixes or not in 4.2 is somewhat moot point since the USBizi firmware isn’t moving forward into 4.2 so we would have no way to take those fixes, but if you were so inclined you could always look at the fixes on codeplex.
@ Brett - Thanks, but I’m probably more lost than most when it comes to figuring out how to make my code efficient enough to run comfortably on the Panda II. Every time I end up spending many hours moving things around, tweaking buffers, and modifying code until my applications are able to startup and run without out of memory errors! It’s all a bit of a mystery to me… especially how the stream classes allocate and deallocate memory. They seem to ignore buffer size parameters, don’t always allocate the exact same amount of memory, and they release a varying amount of that memory when they are closed and disposed.
I tried looking at the 4.1 CPP files on CodePlex with the hope of learning how memory is allocated and deallocated, but quickly got lost in the complexity.
I’m a little concerned based on the experiences that jasdev has discussed. I’m working with this file stuff today and I’m getting these messages “Failed allocation for 685 blocks, 8220 bytes” that we’ve been talking about but everything is working OK. It appears that when there’s a failure GC runs and then everything’s OK. I know I have lots of free memory (34K+) so I suspect there won’t be a problem. But this raises two questions.
I’m only aware of the problem because of the debugger. How do I get this message in my program when I’m not running the debugger? Some kind of exception?
what occurs if the allocation failure isn’t/can’t be corrected?