开发者

Reclaim string memory quickly (device with limited RAM)

I am writing a C# app for a device wit开发者_开发知识库h limited ram. (Mono on iPhone/iPad)

When I assign a large string:

string xml = "10 meg xml string from REST service";

then clear it

xml = null;

Is with the GC free up that memory asap? Is there a way to make sure it's cleaned up. GC has a collect feature, but is this executed right away?

The problem is that I am downloading many large xml files in a loop and even though I am setting the string to null, memory use is growing.


In general GC does not happen immediately because garbage collection is relatively expensive. The runtime generally tries to do it while it's not busy doing other things, but this clearly isn't always possible. I ran into a non-deterministic out of memory error at one point because it was putting off GC too long (sometimes) while I was running a tight memory intensive loop. Lesson: Generally the collector knows what it is doing and you don't need to tweak it. But not always.

To force a collection to happen, you need two lines:

GC.Collect();
GC.WaitForPendingFinalizers();

EDIT: Wrote this before I saw your note on what you were running on. This is written based on the desktop .NET machine. It may (or may not) be different on mono / iPad.


First, keeping large strings or large arrays in memory at once should be avoided, especially on memory constrained devices like phones. Use XmlTextReader, for example, to parse xml files. If you get them from the network, save them to disk, etc.

Next, the issue about garbage collection: the current Mono GC does a conservative scan of the thread stacks, which means that some pointers to objects may be still be visible to the GC, even if to the programmer they have been cleared (like setting to null in your example). To limit the consequences of this behavior, you should try to allocate or otherwise manipulate big arrays and strings in a separate stack frame. For example, instead of coding it this way:

  while (true) {
    string s = get_big_string_from_network ();
    do_something_with_string(s);
    handle_ui ();
    s = null;
  }

do the following:

  void manipulate_big_string() {
    string s = get_big_string_from_network ();
    do_something_with_string(s);
  }
  ...
  while (true) {
    manipulate_big_string ();
    handle_ui ();
  }

Normally, setting a reference to null has the intended effect only when applied to a static or instance field, using it with a method local variable may not be enough to hide the reference from the GC.


I think if you are developing for iPhone you don't have the gargabe collector from the .net framework. The memory management is made by the operating system in this case the iOS.

I think you should check in mono documentation in order to find how to manage the memory in this case. XCode implemented and automatic object management called automatic reference counting and is not a garbage collection like the one in .net framework is just an automatic tool to release unused objects.

Now thinking just in .net when working with big strings, you should always use stringbuilder instead of just string.

Now thinking in the iOS you sould not compare the app written for the iOs enviroment with a Desktop application for windows (in a pc you have a lot more resources). The iOS will not allow a big hit in memory consumption, if an app do this, the operating system will close it automatically to mantain the system running.


While I'm not a Mono expert, but some simple things to check. While you noted that you are setting your variable to null, are you actually calling a .Close() or .Dispose() method as appropriate, or including the scope of the variable in question inside of a using block?

Could be a case of a problem where you're sticking around waiting for a finalizer (i.e. if you have a handle on an unmalaged resource like a file handle), or the variable is still stuck in scope for some reason. This would result in increased memory pressure.

Ideally, handle opening your file one at a time in a method with explicitly clear variable scope in combination with a using block, thus ensuring that the appropriate finalizers, etc. are called even if an exception is thrown.

Hope that helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜