antfarmar / Unity-3D-Asteroids

A simple Asteroids clone. In 3D.
The Unlicense
65 stars 15 forks source link

String Usage: Memory Reduction #22

Closed antfarmar closed 8 years ago

antfarmar commented 8 years ago

C# strings are immutable.

Hence, changing a string variable frequently (e.g. UI text for score) allocates memory at runtime and generates garbage which will invoke a GC call.

ghost commented 8 years ago

A third option could be to use a cache for data driven strings.

string str = CachedFormat("Level {0}", level);

Internally, it can see if "Level {0}" has been generated with the argument provided through 'level' and in that case return a premade string. After N amount of strings have been stored, evict the least likely string to be used again. This approach doesn't work nice if the arguments supplied are unique per call. It works if the arguments always, or usually, are within a determined range.

ghost commented 8 years ago

We can can do an explicit GC.Collect() call in between levels to clean all unreferenced memory.

Sounds like a good approach to me.

ghost commented 8 years ago

We can use a mutable string of characters, as provided by the StringBuilder class in System.Text

But remember that if you need to get a string out from it, a new copy will be constructed (i.e. ToString()). Your systems must accept a StringBuilder reference, I guess, to read characters without instantiating a string instance.

... Unless I am missing your train of thought.

But even then, I get a little confused. Say you have an object foo. If you want a string representation of it, you'd call foo.ToString() - even implicitly as in stringBuilder.AppendFormat("Foo is {0}", foo). I see no way you could evaluate the characters of foo without instantiating the temporary string returned from foo.ToString(). The only way you'd get around string allocation would be to provide an interface on each object that let you query how many characters it wants to generate and then query each character in sequence. int i = foo.CharCount; and char c = foo.GetChar(i); This won't generate garbage but it appear to be slower. A variation would be foo.FillCharArray(charArrayBuffer); where foo can put each character into the array, if it fits.

antfarmar commented 8 years ago

But remember that if you need to get a string out from it, a new copy will be constructed

Yeah, I was expecting that. Just thought I'd throw that option out there for discussion. I guess there's no real way to use C# strings without generating garbage somehow. The explicit GC.Collect() is unnoticeable anyhow between level setup.