본문 바로가기
[ Program ]/c#스터디

40.using/garbage collection

by 관이119 2021. 10. 9.

우리가 클래스 객체를 생성할때 new 를 사용하여 객체를 생성했다.

그런데 객체를 계속 생성하기만 하면 어떻게 될까 라고 생각해볼수 있다.

pc의 메모리는 유한하기때문에 계속객체를 생성하기만 하면 메모리에 수많은 객체가 올라갈것이고 결국 피씨는 다운되거나 제기능을 할수 없을것이다.

그래서 c# 이나 자바에서는 가비지 컬렉션이라는 기능이 있다.

쉽게 생각하면 자동으로 사용하지않는객체를 없애주고 메모리를 청소해주는 기능이라고 생각하면된다.

이 가비지 컬렉션에 대해서는 인터넷에 찾아보면 다양한 의견들이 있고 이야기가 있는데 전체적으로 보면 임의로 호출하는데 상당히 부정적인것을 알수 있다.

결국 알아서 잘하니 임의로 가비지 컬렉션을 하지말고 놔두면 프로그램에 가장좋다고들 이야기한다.

 

그런데 개인적으로 얼마전 어떤생산 라인에 들어가는 프로그램에 온통 가비지 컬렉션을 강제로 호출해놓은것을 보고 없애버렸다.

그런데 그렇게 하니 프로그램이 비정상적으로 작동하기 시작했다.

처음엔 동일하게 작동하다가 시간이 지나면서 계속 정상적으로 작동하던 다른부분들 여기저기에서 계속 문제가 생기며 결과적으로 프로그램이 상당히 느리게 실행되었다.

당연히 정확한 이유는 알수 없었지만 다시 가비지 컬렉션을 강제로 호출하는것만으로 다시 프로그램이 안정적으로 돌기시작했었다.

도저히 이해할수가 없어 나는 테스트를 해보기로 했다.

 

garbige_test1.zip

0.07MB

GC테스트.xlsx

0.34MB

위는 테스트 해본 프로그램과 결과값인데 결론적으로 말하면 내가 느끼기에 가장 빠르고 안정적으로 실행되는 프로그램은 객체를 dispose 해주고 가비지 컬렉션을 강제로 실행한것이었다.

이내용에 대해 정상적으로 객관적인 상황이 아니거나 이정도 근소한 차이는 언제든 당연히 생길수 있다고 이야기하는 사람이 많을것이다.

그래서 해당 테스트결과는 지극히 주관적인 내용임을 먼저 이야기하는 바이다.

 

일단 위내용을 보기전에 객체를 dispose 하는 부분부터 살펴보자.

c나 c++ 에서는 객체를 생성하면 메모리에서 해제해줘야 해당메모리가 사용가능하다는걸 pc 가 인지하고 해당메모리에 다시 데이터를 쓰고 하는 작업을 할수 있다.

코드로 살펴보자

 

TestClass tc = new TestClass();

 

위 예제처럼 만들어주면 해당클래스의 객체가 사용가능한 상태로 메모리에 올라간다.

그리고 해당 객체를 사용하고나면 메모리에 올라가있는 객체를 없애줘야 그 공간을 다른 어떤것이 사용할수 있을것이다.

그래서 tc.dispose(); 를 해주면 메모리에 올라가있는 객체를 없앨수 있다. ( MSDN에서 내용을 읽어보면 바로 해제가 되는게 아닌 해제할수있는 상태로 바꿔준다는게 맞는거같다.)

그런데 막상 아래와같이 테스트해보려면 빌드가 되지 않을것이다.

 

TestClass tc = new TestClass();

tc.dispose();

 

TestClass 에 해당 메서드가 없어서 그런데 이 메서드를 사용하려면 인터페이스를 상속하고 구현해줘야한다.

일단 그냥 다음과 같이 기록해두고 가져다쓰자.

 

public class TestClass : IDisposable
    {
        private bool disposed = false;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    // Manual release of managed resources.
                }
                // Release unmanaged resources.
                disposed = true;
            }
        }

        ~TestClass() { Dispose(false); }
    }

 

해당내용은 아래 경로를 참고 했다.

https://docs.microsoft.com/ko-kr/dotnet/api/system.idisposable?view=net-5.0 

 

IDisposable 인터페이스 (System)

관리되지 않은 리소스 해제를 위한 메커니즘을 제공합니다.Provides a mechanism for releasing unmanaged resources.

docs.microsoft.com

 

그외 프로그램하면서 사용하다보면 dispose가 구현되어있는 클래스들은 그냥 dispose 만 호출해주면 객체가 해제된다.

 

위와 같이 dispose 해주는 역할을 하는 명령어가 있는데 using 이다.

사용방법은 간단하다.

using(객체생성구문)

{

}

위와같이해주면 끝이다.

using 아래 { } 의 내용이 끝나면 객체가 자동으로 dispose가 호출된다.

 

using (StreamReader sr = new StreamReader(@"testpath"))
{
     string str = sr.ReadToEnd();
}

배우진 않았지만 위와같이 streamReader 객체를 using 으로 생성하기만 하면 {} 가 끝나면 자동으로 객체가 해제된다.

 

이제 위 테스트한 예제를 보면 조금은 이해가 될거라고 생각한다.

총4가지의 경우로 실험을 해봤는데

1. 일반적으로 가비지 컬렉션을 실행하지않고 프로그램을 실행하는경우

2. 1번의 상태에서 매번 실행될때마다 가비지컬렉션을 실행한경우

3. 객체를 생성하고 그 객체를 dispose 만 호출해준경우

4. 3번의 상태에서 매번 실행될때마다 가비지컬렉션을 실행한경우

 

 

cpu나 메모리상태는 거의 변화가 없어 성능모니터링을 해봤는데 확실히 가비지 컬렉션을 계속 실행하면 2세대 가비지 수집을 많이 하긴한다. (제어판 > 관리도구 > 성능모니터링)

그런데 가비지 컬렉션수행에 들어가는시간을 계속 모니터링 해보면 가비지 컬렉션을 수행할때와 거의 차이가 없다.

예전에 비해 피씨사양이 너무많이 올라가서 그정도는 영향을 끼치지 않는것인가?

정확한 내용은 알수 없다. 

결국 나는 포로그램 실행시간에 표준편차가 가장작고 , 실행시간이 가장빠른프로그램이 가장 안정적이다고 생각이 들어 4번이 안정적이다고 느꼈다.

하지만 계속 여기저기 가비지 컬렉션에 대해 나와있는 글들을 보면 여러가지 이유로 절대 사용하지 말라고 되어있어 아직도 고민스러운건 사실이다.

 

가비지 컬렉션에 대해 여러가지 잘이야기된곳은 아래 경로이니 한번 내용을 읽어보자.

http://www.simpleisbest.net/post/2011/04/01/Review-NET-Garbage-Collection.aspx

 

SimpleIsBest.NET | 닷넷 가비지 컬렉션 다시 보기 - Part I

CLR(Common Language Runtime)의 가비지 컬렉션(Garbage Collection)의 작동 원리를 파악한다는 것은 매우 중요한 일입니다. 가비지 컬렉션의 작동 방식을 충분히 파악해야만 어플리케이션의 메모리 문제를

www.simpleisbest.net

 

프로그램에 정답은 없다고 생각한다.

자원을 많이 먹고 나쁘다고해도 실제로 사용자가 느끼기에 빠르고 오류없이 잘돌아가면 그또한 괜찮지않을까 생각은 해본다.

경험이 많고 많이 아는 수많은 사람들이 쓰지말라고해서 사용하기 조심스럽지만 정말 지금당장 급박한 상황인데 프로그램이 조금이라도 빨리지거나 안정적으로 작동하는것처럼 보여야한다면 객체를 dispose 해주고 가비지 컬렉션을 실행하는것도 하나의 방법이지 않을까 생각해본다.(물론 욕먹는건 책임질수없다.)

단, 위내용은 클라이언트 프로그램에서만 생각해봐야한다. 웹프로그램 에서 Gc.Collect 를 난발한다면 하나의 서버에 여러명의 사용자가 사용하는 상태라서 자원사용량이 어마해질것으로 생각된다.

 

 

***숙제 : 가비지 컬렉션에 대한 자신의 생각을 말해보자.

'[ Program ] > c#스터디' 카테고리의 다른 글

42. 상속  (0) 2021.10.09
41.arraylist / List / StringBuilder / 참조추가법  (0) 2021.10.09
39.property(속성)  (0) 2021.10.09
38.const/enum/struct  (0) 2021.10.09
37.DateTime,static  (0) 2021.10.09

댓글