아이템 15: 불필요한 객체를 만들지 말라

가비지 수집기는 사용자를 대신하여 메모리를 관리한다.

하지만 이러한 작업이 아무리 효율적이라 하더라도 힙에서 새로운 객체를 생성하고 삭제하는 작업은 그러한 일을 전혀 하지 않는 것에 비한다면 상대적으로 많은 프로세서 시간을 사용하는 것은 사실이며, 너무 많은 객체를 생성하면 심각한 성능 문제를 일으킬 수도 있다.

따라서 가비지 수집기가 과도하게 동작하지 않도록 주의해야 한다.

기술적으로 몇 가지만 유념하면 가바지 수집기의 작업을 현저히 줄일 수 있다.

모든 참조 타입의 객체는 그것이 설사 지역 변수라 하더라도 동적으로 메모리를 할당한다.

이렇게 할당된 객체는 이 객체를 참조하는 상위 객체가 삭제되면 가비지가 된다.

지역변수의 경우 그 변수를 선언한 메서드를 벗어나는 순간 가비지가 되어 더 이상 살아 있는 객체로 간주되지 않는다.

ex) Update에서 동적 할당 등

이러한 경우를 막기 위해 해당 객체를 멤버 변수로 두고 이를 재사용 하는 방법이 있다.(캐싱)

자주 호출되는 메서드 내에서 참조 타입의 객체를 매번 생성하는 경우라면 지역변수를 멤버 변수로 변경하자.

물론 호출 빈도가 빈번하지 않은 경우라면 굳이 변경할 필요는 없다.

지역변수를 모조리 멤버 변수로 변경하여 동일한 객체를 생성하는 것을 완전히 피하라는 것이 아니다.

자주 사용되는 참조 타입의 인스턴스를 정적 멤버 변수로 선언하는 방법

원도우에 검정색으로 무엇을 그리려면 반드시 검정 브러시가 필요하다.

그런데 매번 새로운 검정 브러시를 생성하면 금세 엄청난 수의 검정 브러시가 생성될 것이고 이후 모두 삭제해야 한다.

앞서 알아본 방법처럼 지역변수를 멤버 변수로 변경하면 상당히 도움이 되겠지만 충분하지는 않다.

프로그램이 실행되는 동안 수십 개의 창과 컨트롤들이 생성될 텐데 그 때마다 수십 개의 검정 브러시를 생성할 것이기 때문이다.

.NET은 이러한 문제를 해결하기 위해 System.Drawing.Brush 클래스에 미리 생성된 브러시를 반환하는 정적 메서드를 제공한다.

지연 Lazy 알고리즘을 사용하여 구현

private static Brush blackBrush;

public static Brush BlackBrush
{
    get
    {
        if (blackBrush == null)
        {
            blackBrush = new SolidBrush(Color.Black);
        }
        return blackBrush;
    }
}

이 코드는 검정 브러시를 최초로 요청했을 때 비로소 해당 객체를 생성하는 것을 알 수 있다.(Lazy)

Brushes 클래스는 이렇게 생성된 검정 브러시를 저장해두고 동일한 요청이 있을 때 마다 이 객체를 돌려준다.

결국 검정 브러시 하나를 영원히 재사용하게 된다.

즉, 응용프로그램에서 라임색 브러시를 요청하지 않는다면 해당 브러시는 생성되지 않는다.

이런 방법은 객체 수를 최소화할 수 있지만 동시에 부정적인 측면도 있다.

경우에 따라서 생성된 객체가 메모리상에 필요 이상으로 오랫동안 남아 있을 수 있다는 점이다.

또한 Dispose() 메서드를 호출해야 할 시점을 결정할 수 없기 때문에 비관리 리소스를 삭제할 수 없다는 것도 매우 큰 단점이다.

앞서 응용프로그램의 성능에 영향을 주지 않기 위해서 객체 생성을 최소화하기 위한 두 가지 기법을 살펴봤다.

첫 번째 방법은 자주 사용되는 지역변수를 멤버 변수로 변경하는 것이다.

두 번째 방법은 종속성 삽입을 활용하여 자주 사용되는 객체를 생성했다가 이를 재활용하는 것이다.

마지막으로 알아볼 기법은 변경 불가능한 타입과 관련된 부분이다.

변경 불가능한 타입의 대표적인 예로는 System.String이 있다.

string객체가 생성되면 이 객체가 가지고 있는 문자열은 수정이 불가능하다.

실제 프로그램에서 변경되는 것 처럼 보이는 것은 새로운 객체를 할당하는 것, 당연하게 이전 객체는 가비지가 된다.

따라서 문자열 보간을 사용하거나, StringBuiler를 사용하라

댓글남기기