사용자 도구

사이트 도구


kb:luagarbagecollection

Lua Garbage Collection

가비지 컬렉션이란 사용자가 생성한 동적 객체를 명시적으로 지워주지 않아도, 가상 머신 자체가 이를 알아서 삭제해주는 기능을 말한다. 주로 참조 카운팅을 이용한다. 다른 방법이 있기는 한가? 어쨌든 루아도 마찬가지로 참조 카운팅을 사용한다.

가비지 컬렉션의 대상

기본적으로 가비지 컬렉션의 대상이 되는 것은 오브젝트다. 루아에서 오브젝트로 분류되는 것은 테이블, 함수(클로져, 청크도 포함), 풀 유저데이터다. 숫자, 문자열, 라이트 유저데이터는 가비지 컬렉션의 대상이 되지 않는다. (문자열은 좀 틀리지만…)

또한 오브젝트라고 해서 모두 가비지 컬렉션의 대상이 되는 것은 아니다.

  • 스택 탑을 lua_settop 함수를 이용해 원래 위치보다 낮게 설정해 버리는 경우, 그 위에 있던 아이템들은 수집되지 않는다.
  • 테이블에 키나 값으로서 등록된 오브젝트는 수집되지 않는다. 그 오브젝트를 가르키는 변수가 없더라도, 테이블 자체가 그 오브젝트를 참조하고 있기 때문이다. 이 말은 즉 전역 오브젝트들은 수집되지 않는다는 말이다. 전역 오브젝트는 전역 테이블에 등록되어 있으니깐.

이런 경우, 오브젝트를 명시적으로 삭제해주기 위해서는 X = nil 형식의 구문을 사용하면 된다.

위크 테이블(Weak Table)

테이블 안의 오브젝트가 쓸모없다고 판단한 경우, X.Y = nil 형식의 구문을 사용하는 것도 좋다만, 매번 일일이 이런 식으로 삭제해주는 것도 못할 짓이다. 이런 경우 루아에서 제공하는 위크 테이블 기능을 사용하는 것이 낫다.

위크 테이블 안에 있는 오브젝트들은, 테이블 자체가 그 오브젝트를 참조하고 있더라도, 가비지 컬렉션의 대상이 된다. 즉 테이블의 오브젝트에 대한 참조 카운트가 가비지 컬렉션을 막지 못한다는 것이다.

임의의 테이블을 위크 테이블로 만들기 위해서는 메타테이블과 __mode 메타메서드를 설정해줘야한다.

> a = {}
> b = {}
> setmetatable(a, b)
> b.__mode = "k"        -- a 테이블의 키는 '위크' 키다.
> key = {}              -- 첫번째 키를 생성한다.
> a[key] = 1
> key = {}              -- 두번째 키를 생성한다.
> a[key] = 2
> for k, v in pairs(a) do print(k, v) end
table: 0034B9E8 2
table: 0034B5C8 1
> collectgarbage()
> for k, v in pairs(a) do print(k, v) end
table: 0034B9E8 2

두번째 키를 생성해서 테이블에다 값을 대입한 시점에서, 첫번째 키로서 사용했던 테이블은 a 테이블 자체 외에는 더 이상 참조가 존재하지 않는다. a 테이블은 키 값이 “위크”이므로 가비지 컬렉션을 수행하면 삭제되는 것을 볼 수 있다.

예상할 수 있겠지만, 키만 “위크”로 설정할 수 있는 것은 아니다. 값도 “위크”로 설정할 수 있다. 물론 둘 다도 가능하다.

b.__mode = "v"  -- "값"을 위크로 설정한다.
b.__mode = "kv" -- "키"와 "값" 모두를 위크로 설정한다.

그러나 키가 위크냐, 값이 위크냐에 따라 상관없이 둘 중에 하나라도 위크값이고, 참조가 테이블 자체 외에는 없어지면, 키와 값 모두 테이블에서 삭제된다.

루아 관련 함수

  • 루아 내에서 사용할 수 있는 함수
    • gcinfo, collectgarbage
  • C 쪽에서 사용할 수 있는 함수

링크

kb/luagarbagecollection.txt · 마지막으로 수정됨: 2014/11/14 15:49 저자 excel96