본문 바로가기

Language/C#

GC를 유발하는 몇가지 Case

ToString(), ToArray()등의 data converting method


C#에서 지원하는 대부분의 data type은 ToString이라는 method를 지원한다.

이는 data를 string으로 변환하는 method인데 정확히 말하자면 string을 allocation(새로 할당)하여 해당 string에 data의 type,

값 자체를 쓴다.

우리가 주목해야 할 부분은 string을 새로 만드는데에 있다.

대부분 코드에서 ToString을 남발하는데 매 frame마다 호출되는 Update method에서 ToString을 남발했다가는

심각한 frame drop이 발생할 것 이므로 사용을 자제해야 한다.



string +연산자 사용


문자열과 문자열을 합쳐주는 ' + ' 연산자는 사용시 비용이 발생한다.

C#에서의 String객체의 경우 한번 생성자로 생성하고 나면 내부의 값을 변경할 수 없다.

따라서 새로운 값이 동일 변수에 할당되면 이는 내부적으로 새로운 string객체를 생성하고

새로운 값을 할당한 후 동일 변수에 치환하게 된다.

그리고 이전에 사용하던 string객체는 GC가 처리하게되는데 이 과정이 바로 문제인것이다.


이는 .NET의 StringBuilder Class를 사용하면 해결할 수 있다.

물론 Stringbuilder class의 경우도 내부적으로 buffer가 부족하면 기존 buffer의 2개에 해당되는 새 buffer를 할당하고

여기에 data를 복제하게 된다.

하지만 해당 Stringbuilder 객체를 해제하고 새로 객체를 할당하는것은 아니다.

또한 Stringbuilder의 경우 capacity를 객체 생성시에 지정할 수 있다.



    
public string Get1ToN_Bad(int n)
{
    string s = "";
    for(int i = 1 ; i <= n ; i++)
    {
         s += i.ToString( ) + "."; 
     }
    return s;
}



    
public string Get1ToN_Bad(int n)
{
    StringBuilder sb = new StringBuilder( );
    for(int i = 1 ; i <= n ; i++)
    {
         sb.Append(i.ToString( ) + ".");
     }
    return sb.ToString( );
}





Boxing, Stack data를 Object로 변환할때


여기서 우리가 주의깊게 봐야할 점은 버려지는 memory인데 여기서 버려지는 memory는 stack에 존재하는 단순 값들의 obejct로 반환할 때 생기는 일이다.

이런 일은 잘 발생하지 않지만 짚고 가겠다.



    
int i = 123;
object o = (object)i; // explicit boxing


위 코드처럼 객체가 아닌 stack에 존재하는 data를 boxing할 때 사본은 heap에 생성하므로 잠시 이용하고 버려지는

memory가 발생하게 된다.








참고

https://hrmrzizon.github.io/2017/04/23/garbage-collector-in-unity/

string 참고

http://www.csharpstudy.com/Mistake/Article/3

'Language > C#' 카테고리의 다른 글

Collection의 성능문제 / Generic Collection  (0) 2019.03.06
C# 제네릭  (0) 2019.03.06
Mono / Nuget / .NET Framework / .NET Core / Xamarin / Manifest  (0) 2019.02.27
Dictionary  (0) 2019.02.27
ref, out, Tryparse Keyword  (0) 2019.02.26