반응형


http://cafe.naver.com/unityhub/25942


아래 개미개발자님의 코드 스타일의 최적화 이슈의 문제에 질답이 오가던 중, 
메테오님의 지적으로 동안 제가 잘 못 알고 있었던게 있었더군요. 

그래서 많은 분들이 알고 계시지만, 혹시나 다른 분들도 같은 오해에 빠져 계시지 않은까 해서 글을 남깁니다. 

논쟁은 new Vector3()를 하면 할당 되는 곳이 힙이냐 스택이냐 였습니다.

일단 제가 정보를 얻은 곳은,

===========================================================
1.

"vector야 말로 string 과 더불어 가장 많이 생성되는 클래스가 아닐까;

특히 vector3 v= new vector3(1,2,3) 이런거,.. 근데 이 벡터를 new로 할당하게 되면 heap에서 메모리 할당이 일어난다고 한다. 뭐 당연하 이야기인데..."

2.

"메소드 안에서 new 

Vector3를 메소드에서 new로 생성하는 코드들. 변수가 가비지로 생성한다. 
자주 호출되는 경우. 멤버변수로 선언해서 사용하자. 
메소드 안에서만 사용되는 인스턴스. 
구조체로 바꾸자. 스택에 생성되니까 "
========================================================


보통 c++, java에서 new를 하면 구조체도 힙에 할당되는데, 아마도 이 고정 관념때문에 생긴게 아닌가 합니다.

메테오님이 스택에 생성된다는 말을 듣고 찾아보니,


========================================================
using System;
struct SimpleStruct
{
    (생략)
}

class TestClass
{
    public static void Main()
    {
        SimpleStruct ss = new SimpleStruct();
       (생략)
    }
}

Heap or Stack?
When you call the New operator on a class, it will be allocated on the heap. 
However, when you instantiate a struct, it gets created on the stack. 
This will yield performance gains. Also, you will not be dealing with references 
to an instance of a struct as you would with classes. 
You will be working directly with the struct instance. 
Because of this, when passing a struct to a method, 
it's passed by value instead of as a reference.
========================================================

그리고 유니티 코리아 질답에

transform 의 position 을 변경하고자 set 함수를 사용하였는데 값이 반영이 되지 않더라고요,

그런데 transform.position = new Vector3( x, y, z); 처럼 새로 할당하니 값이 반영 되고요.

인터넷에 뒤져봐도 다들 새로 할당하는 것으로 코딩이 되더라고요.

단순 값만 변경하고자 하는데 할당을 해야하는지 의문이 듭니다.


"new로 할당한다고 하더라도 구조체는 여전히 스택에 생성되는 값 타입이다. 
C#이 이 문법을 지원하는 이유는 통일성과 생성자 호출을 위해서이다."

라는 답글이 달려있었더군요.

뭐, 공식 문서에서 스택에 저장 된다고 하니 믿어야겠지만, 유니티가 뒤통수 치는거 잘하니 한번 검증 해봤습니다.
공포의 업데이트문에 

case1 클래스 생성과 
case2 Vector, Color 구조체 생성

을 각각 10만번 루트를 돌려봤습니다.

결과는 case1 의 경우는 5.3MB의 가비지가 생기는데, case2는 가비지 자체가 생기기 않는 군요.


결론은 

"걱정 없이 new Vector3() 쓰세요."

입니다. 


-------------검증 코드---------------
public class NewBehaviourScript : MonoBehaviour {

public class Test{
int i,j,k,m,q,e,f,g,x,c,h,y;
}
void Start () {
}
void Update () {

for (int i=0; i<100000; i++) {
// case 1 클래스 할당 소스
Test t=new Test();

// case 2 구조체 할당 소스
Vector3 v = new Vector3 (); 
v.x = 1f;
v.y = 1f;
v.z = 1f;

Color c=new Color();
c.r=1f;
c.g=1f;
c.b=1f;
c.a=1f;
}
}

case 1 프로 파일러 (GC Alloc 5.3MB)




case 2 프로파일러 (GC Alloc 0B)



참고로 메모리풀관려 질문이 많이 올라와서 위 내용을 찾다가 좋은 글이 있어 링크 남깁니다.


반응형

+ Recent posts