
이 포스팅은 제가 직접 공부하고 제 방식대로 내용을 정리한 글입니다.
using System;
public class Logger
{
public string LogMessages { get; private set; }
public Logger()
{
LogMessages = string.Empty;
}
public void Log(string message)
{
LogMessages += message + "\n";
}
}
public class Program
{
public static void Main()
{
Logger logger = new Logger();
for (int i = 0; i < 10000; i++)
{
logger.Log("This is log message number " + i);
}
Console.WriteLine("Logging completed. Total log length: " + logger.LogMessages.Length);
}
}
Q1. 위의 코드가 문제가 되는 이유를 메모리 관점에서 설명해주세요.
A1. 메모리 관점에서 보면
Logger 클래스의Log() 메서드부분에서 문제가 생깁니다.string + string을 하게 되면 힙 메모리가 증가하게 됩니다. string은char[]로 배열이기에 참조 타입이기 때문입니다. 가장 큰 문제는 힙 메모리가 증가하게 되면서 해당 데이터는 GC의 먹잇감이 됩니다. 이는 성능에 큰 영향을 미칩니다.Q2. 아래와 같이 string이 아닌 StringBuilder가 권장되는 이유는 무엇일까요?
public class Logger
{
private StringBuilder logMessages;
public Logger()
{
logMessages = new StringBuilder();
}
public void Log(string message)
{
logMessages.Append(message).Append("\n");
}
public override string ToString()
{
return logMessages.ToString();
}
}
A2. string의 경우, StringBuilder과 달리 가변적인 문자열 버퍼를 사용하여 처리하기에, 문자열을 변경할 때 새로운 문자열 객체를 생성하지 않습니다.
Q1. 가비지 컬렉터란 무엇인가요?
A1. CLR의 메모리 관리 소프트웨어로, 할당할 힙 메모리 공간이 부족할 때, 가비지 컬렉터가 힙 메모리를 돌며 사용하지 않는 메모리를 회수합니다.
Q2. 가비지 컬렉터의 장점과 단점에 대해 설명해주세요.
A2.
장점 : GC가 자동으로 메모리를 해제해주기 때문에 편리합니다.단점 : 가비지 컬렉터가 실행되면 일시적으로 프로그램의 성능이 저하가 될 수 있으며, 실행 시점을 예측할 수 없습니다.
Q3. 가비지 컬렉터의 세대 개념에 대해 설명해주세요.
A3. 메모리 구역을 나누어 메모리에서 빨리 해제될 객체와 오래도록 살아남을 것 같은 객체들을 구분합니다.
0, 1, 2의 3개의 세대로 나눕니다.
0세대는 가비지 컬렉터를 한 번도 겪지 않은 객체들이 위치 -> 단명 객체들이 많아 가비지 컬렉터가 자주 발생합니다.
1세대에는 0세대를 통과하고 살아남은 객체들이 위치합니다.
2세대에는 오래된 객체들이 위치한다. 이 세대에서는 가비지 컬렉션은 가장 드물게 발생합니다.
Q4. 박싱, 언박싱을 사용할 때 주의해야 할 점은 무엇일까요?
A4. 박싱 언박싱을 하는 과정에서 데이터를 메모리의 다른 위치로 이동시키는데, 이 때 추가적인 메모리 할당 및 해제 과정에서 힙에 쓰레기 메모리가 쌓여 GC에 부하를 줄 수 았습니다.
Q5. 오브젝트 풀을 사용하면 메모리 관리에 도움이 되는 이유가 무엇일까요?
A5. 객체를 미리 생성 후 파괴하지 않고 재사용합니다.
- 자주 생성 / 삭제가 일어나는 오브젝트에 오브젝트 풀링을 사용하면 메모리 및 GC 관리를 할 수 있습니다.