[t:/]$ 지식_

go에서는 값을 리턴하는 것이 낫다.

2020/06/08

이제는 거울 앞에 선 꼰대 C프로그래머들을 보라. 함수의 리턴으로 구조체 값을 쓰는 것은 생각해 본 적도 없다.

어.. 그거 구조체가 스택에 생성되는데 그거 바로 리턴하면 스택 뿌서지면서 휘발되지 않아? 아참 아니지.. 안 써봐서 그렇지 구조체를 리턴하면 값을 리턴하는 결과가 되면서 스택을 복사해가는 거지.. 아 그렇지 아규먼트와 리턴 값은 스택을 통해서 이뤄지는 것이니 구조체도 그렇지. 찾아보니 온전히 잘 된다는 것 같다. 아니 구조체를 리턴해 본 적이 없다니까? 포인터만 리턴해봤지.

그리하여 go의 경우를 실험해봤다. 얘는 GC 해주고 뭐 알아서 해주는 것이 많으니 함수 내에 선언한 구조체 변수의 포인터를 리턴하면 빠르지 않을까? 즉, 상상도는 이렇다.

  1. 함수 내에서 구조체 선언. 스택에 공간 확보. 스택에 공간 확보라는 건 크기 만큼 주소 옵셋만 주면 되는 과정이다. 힙 처럼 빈 블럭 찾고 쑈 할일이 없음.
  2. 구조체에 값을 할당하고 뭐 할 일을 함
  3. 구조체 포인터를 리턴
  4. ...아... 스택 뿌사지면서 구조체 내용 날아가니까.. 그거 막기 위해 go가 어찌저찌 미리 컴파일 타임에 하겠네.. 리턴할 구조체는 따로 힙에서 할당 받아서 그 주소를 리턴하겠네? ... 여기까지만 생각해도 포인터 리턴은 안 빠르겠구나로 셀프 답변이 나와버림..

실험하고 찾아보니 4번 항목은 그런 것이었던 것이다.. 스택에 잡아둔 구조체를 날려먹지 않기 위해서 go가 힙에서 메모리를 가져오고 거기에 복사하고 그 주소를 포인터로 리턴한다는 것. 즉, 지지고 볶고 구간이 들어간다. 실제로는 훨씬 더 지지고 볶는다.

그냥 값으로 리턴하면 어떨까? 복사는 매한가지이지만 스택에서 복사하고 땡이다. 힙 할당 과정이 필요없는 것. 위에 썼지만 스택 할당이라는 것은 그냥 크기 만큼 오프셋 이동하는게 전부임.

이미 자세히 실험한 사람이 있다.

https://philpearl.github.io/post/bad_go_pointer_returns/

왐마.. 포인터 리턴한다고 뭔 일을 저리 많이 하는 겨..

결론 1 : 구조체도 그냥 값으로 리턴 하는 것이 빠름.
결론 2 : 데이터 lifetime이 짧으면 더욱 그러함. (즉각적으로 GC가 개입하므로 그렇다는 듯?)

그렇다면 이미 할당된 버퍼를 함수에 포인터로 넘겨주면 어떨까? 그게 젤 좋다. 그런데 go에서는 포인터 변수에 인덱싱도 덧셈 뺄셈도 안 되니 영..뭐 할 수 있는 것을 잘 모르겠다... 찬찬히 공부해 보는 것으로..

전설의 임인건님 책을 읽고 포인터의 뺄셈은 의미없다고 알고 있는 분들이 있는데 안 그렇습니다. 포인터를 빼서 엉망진창 쓰까진 자료형의 타입을 추론하거나 두 포인터 사이에 아이템이 몇 개인가 계산 할 수도 있고 그래요..









[t:/] is not "technology - root". dawnsea, rss