2

I already got the idea that string variables are immutable, so the they are copied to another place in heap every time we make a change, and since GarbageCollector has to collect them all the time, it causes performance issues..

Question is:

  • Integers or doubles are immutable too. Are they also copied any time we make a change?
  • If so, are all copies are collected by garbage collector too?
  • Nobody complains about performance about keep changing integers, ever. Is that because there is no point because their allocated memory has to be always the same (8 bit, 16 bit etc), unlike strings?
1
  • 1
    Integers are value types, which "saved" in the stack memory. When variable of value types goes out of scope it will be removed from the stack. No need for garbage collector.
    – Fabio
    Commented Mar 31, 2017 at 22:10

1 Answer 1

3

Whilst both strings and integers are immutable, they aren't the same. Strings are immutable reference types; integers are immutable value types.

If you have a string variable, s, then it simply holds a reference (a pointer) to the location in the heap where that string object is stored. If you change the string that s refers to, then potentially a new string object is created on the heap and the original one is then eligible for garbage collection if no other references to it remain.

If you however have an int variable, i, then it holds the integer value. If you change the number held by i, then that value changes. There is no new heap allocation.

It certainly isn't the case that if you change strings, "the GarbageCollector has to collect them all the time". The garbage collector only runs when it needs to; it's quite possible that during the life of your app, it'll never run. And even when it does run, it can be very fast and not cause performance problems. I'm not saying it never has performance problems; but I am saying that changing strings all the time does not guarantee performance problems.

Edit

Regarding StringBuilder, this is a memory copying issue; not a garbage collection one. By way of example, consider the following code:

var strings = GetListOf1000StringsEach100CharactersLong();
var finalString = "";
foreach (var item in strings)
{
    finalString += item;
}

What happens when you run that is:

  • First time around, the 100 characters in strings[0] is copied to a new location, referenced by finalString.
  • Second time through the loop, those 100 characters in finalString, plus the 100 in strings[1] are copied to a new location and finalString updated to point at that location.
  • Third time, those 200 characters in finalString, plus the 100 in strings[2] are copied to a new location and finalString updated to point at that location...
  • On the last pass, those 99900 characters in finalString, plus the 100 in strings[999] are copied to a new location and finalString updated to point at that location!

As it loops through, the number of characters that has to be copied grows, and those same characters are copied over and over. This is a huge performance problem. StringBuilder solves it by just storing references to the original strings and only doing that copy once, when ToString() is called. This gives a big performance boost. But it is unrelated to garbage collection.

12
  • That filled out the gap in my mind, thanks. I didnt know GC might never run though. Then why are people are so obsessive about using StringBuilder instead of String?
    – Pecheneg
    Commented Mar 31, 2017 at 11:39
  • 2
    @NecatiHakanErdogan David is saying "the GC might never run" in the case of a short lived program. For example a command line utility that starts up does its job and then shuts down. It may never produce enough garbage for running the GC to make sense because the GC isn't looking to ensure no garbage, its looking to ensure you have enough memory left to do you work. Even for long lived programs it won't run "all the time" but "every few seconds" or "every few minutes" or "every few hours" depending on how much garbage your program produces Commented Mar 31, 2017 at 11:47
  • 1
    @NecatiHakanErdogan, I have updated my answer to explain why StringBuilder improves performance.
    – David Arno
    Commented Mar 31, 2017 at 12:49
  • 1
    @NecatiHakanErdogan If you're wondering why you should use StringBuilder, you probably haven't met Shlemiel the Painter?
    – Doval
    Commented Mar 31, 2017 at 14:17
  • 2
    @Necati the reason I bring it up is that memory isn't the only cost when you're not using a StringBuilder in a loop - you're also wasting CPU copying the same characters over and over into new strings. This isn't a problem for fixed size numbers because addition/multiplication/etc take roughly the same amount of time regardless of what the value of the numbers are.
    – Doval
    Commented Mar 31, 2017 at 20:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.