XNA Creators Club Online
Page 1 of 2 (26 items) 1 2 Next >
Sort Posts: Previous Next

Avoiding int.ToString() GC garbage

Last post 09-24-2008 5:20 AM by nop. 25 replies.
  • 08-27-2008 6:54 AM

    Avoiding int.ToString() GC garbage

     

    I am currently reducing the number of managed bytes allocated to stop GC glitching. By commenting out most of my code I have narrowed a problem. Every time I need an int in string form ie.

    displayText = "Lives Used: " + game.LivesUsed.ToString(); 

    it allocates 7KB of managed memory every second (in 240 objects). This is trivial for just one but if I'm doing this in 30 different places then I'm going to get hit with a GC collect every 5 seconds or so *just* from one tiny section of the over all game...

    Does anyone know a good way around this? I hope I'm not going to have to store a text version of every int I want to display and update it every time the int changes!

  • 08-27-2008 7:05 AM In reply to

    Re: Avoiding int.ToString() GC garbage

    One way is to only update the displayText in the set of LivesUsed property for eg.

    public int LivesUsed

    {

    get{return _livesUsed;}

    set{

    _displayText="Lives Used: "+value.ToString();

    _livesUsed=value;

    }

    That way its only ever set when the property changes instead of 60 times per second. this should save you a lot of garbage

    Also for added benefit, add "Lives Used: " to a resource file.


  • 08-27-2008 10:27 AM In reply to

    Re: Avoiding int.ToString() GC garbage

    conkerjo:

    set{

    _displayText="Lives Used: "+value.ToString();

    _livesUsed=value;

    }

    I'm hoping to avoid that approach because most of them aren't really set() as propertys like that...

  • 08-27-2008 10:35 AM In reply to

    Re: Avoiding int.ToString() GC garbage

    Have you tried using a StringBuilder for the string concatenation? This will not create additional garbage when adding two strings.
  • 08-27-2008 1:32 PM In reply to

    Re: Avoiding int.ToString() GC garbage

    I'm not sure that's true Melvil ... in fact, I'm pretty sure it's quite the opposite ... when you only have a trivial concatenation to do such as two or three strings, it's better to just use the + method. StringBuilder is useful if you have to build up a large string from an unknown number of iterations, such as when building an html table in asp.net.

    The suggestion to only update the displaytext when the value actually changes is the best one ... it ensures that you only allocate when necessary (you can't avoid allocating a new string when you have to change it ... it's a value type). You probably want to refactor your code so that it works with the set technique :-)

    Joel Martinez - XNA MVP  
    Blog: http://codecube.net
    Play Videos on an XNA Texture: Scurvy Media
    XNA Unit Testing: Scurvy Test
  • 08-27-2008 2:27 PM In reply to

    Re: Avoiding int.ToString() GC garbage

    Joel Martinez:
    I'm not sure that's true Melvil ... in fact, I'm pretty sure it's quite the opposite ... when you only have a trivial concatenation to do such as two or three strings, it's better to just use the + method.

    This of course totally depends on the use case. While it might be overhead for this simple case, it might be faster when he later plans to concatenate more strings. In such cases I always try both methods, see which produce less garbage and go with the better one. Of course, combined with the property method that only updates the string when necessary you can reduce the garbage creation to a minimum, that's why I'd also suggest this solution.

  • 08-27-2008 9:17 PM In reply to

    Re: Avoiding int.ToString() GC garbage

    Joel Martinez:
    The suggestion to only update the displaytext when the value actually changes is the best one ... it ensures that you only allocate when necessary (you can't avoid allocating a new string when you have to change it ... it's a value type).

    But the fact that it's a value type means that it shouldn't be putting anything on to the GC heap right? That was my understanding anyways...

  • 08-27-2008 9:20 PM In reply to

    Re: Avoiding int.ToString() GC garbage

    reedake2:

    Joel Martinez:
    The suggestion to only update the displaytext when the value actually changes is the best one ... it ensures that you only allocate when necessary (you can't avoid allocating a new string when you have to change it ... it's a value type).

    But the fact that it's a value type means that it shouldn't be putting anything on to the GC heap right? That was my understanding anyways...

    An int is a value type, but a string is not. In this small example:

    string text = "Lives: " + lives.ToString();

    You actually are allocating three strings, two garbage and one stored in text (which likely goes out of scope at the end of the method and becomes garbage itself). It's always best to only update strings when the data changes. This is a prime reason why you should use properties for things like these. Then you could easily implement the suggestion above and be done. If you don't have it set up that way now, I would change it to set up that way. This tiny operation is allocating 180 strings per second, tons of wasted garbage that is sure to ruin your day on the Xbox 360 if you do it with other variables as well.

  • 08-27-2008 9:22 PM In reply to

    Re: Avoiding int.ToString() GC garbage

    Strings are reference types. They are a primitive type, and they are immutable (which in many ways makes them behave similar to what people are used to with value types, and means you cannot create new ones without heap allocations) but they are allocated on the heap, not the stack.
    XNA Framework Developer - blog - homepage
  • 08-28-2008 3:21 AM In reply to

    Re: Avoiding int.ToString() GC garbage

    Nick Gravelyn:
    This is a prime reason why you should use properties for things like these. Then you could easily implement the suggestion above and be done.

    Yeah, it's one of those new things to me that I've not yet got into a habbit of doing. Do you generally have *all* of your public variables as properties? Because that would be a very tedious process for some of my classes...

  • 08-28-2008 3:33 AM In reply to

    Re: Avoiding int.ToString() GC garbage


    reedake2:

    Nick Gravelyn:
    This is a prime reason why you should use properties for things like these. Then you could easily implement the suggestion above and be done.

    Yeah, it's one of those new things to me that I've not yet got into a habbit of doing. Do you generally have *all* of your public variables as properties? Because that would be a very tedious process for some of my classes...

    I don't do it for all values, no. In fact the large majority of my variables are just public fields. I generally make a property when either A) I need to do some sort of data constraint on the input values (such as making sure a value is clamped between two values, or something similar) or B) I will be displaying the data as text. Otherwise I generally stick with public fields.

    I also take into account the data type. For things like ints, floats, and strings, there's not much difference between using a public field and property. However for a Vector2 or other struct, there is because you can no longer change a single component on the property since the value returned is actually a copy of the original data. So for those I usually use public fields so I can change a single component of the vector more easily.
  • 08-28-2008 7:35 PM In reply to

    Re: Avoiding int.ToString() GC garbage

    Well, if you're absolutely set on getting rid of those allocations you can write your own string formatting routines that format text directly into a char[ ] and then write your own text rendering system and give it a DrawString( char[ ] textChars, int charsToDraw ) method so you can draw straight out of that array without having to call ToString all over the place. Then you just make one big text buffer at load time and keep reusing it. It's a fair bit of work to go to to get rid of a few allocations, but as you said even a few ToStrings per frame can add up.

    That's what I've done in my project. Come to think of it I should probably clean up the code and release it or something...