[t:/]$ 지식_

go의 string, []byte 변환은 돈이 든다.

2020/06/09

회사 일 때문에 go를 좀 띄엄띄엄 보고 있는데.. string과 byte 배열을 엄격하게 쓰는 것을 보고 아.. 얘네는 계획이 있구나.. 현대 언어 답게 유니코드 대응이든 뭐든 문자열을 문자열답게 쓰고자 byte 배열과 구분했구나 하는 느낌이 들었다. (아직은 잘 모름)

찾아보니 결과는 거의 그렇다. []byte와 string을 서로 변환하는 것은 포인터만 찍고 캐스팅 하는 것이 아니다. 힙 할당도 받고 복사도 한다. 몇 푼어치 안 되는 비용이지만 어떤 업무에서는 큰 비용이다.

따라서 아예 conversion없이 처리할 수 있다면 그리 하는게 성능상 이득이다. go에서 casting 이라는 단어를 쓰지 않고 conversion이라는 단어를 쓰는 것은 아마도 이런 이유에서 온 것이다. C에서는 포인터를 뭘로 변환하든 실제 포인터의 값이 변하지는 않는다. 컴파일러가 데이터 형의 메타를 다룰 수 있도록 알려주는 것 뿐이다. 이것이 캐스팅이다. 그러나 go에서는 casting을 하지 않고 진짜 번역과 같은 행동을 취한다. 예컨데 []byte를 string으로 변환하면 새 공간을 할당하여 복사를 한다. 그래서 conversion이라는 단어가 유효하다.

소켓이나 http 서버라고 생각해보자. (나는 아직 go의 http를 공부하지 않았음을 참고) 기계적으로 짤 경우 read 하고 그거 내가 만든 자료형에 넣기위해 문자열화하고 (1 컨버전) 거기서 또 숫자 같은 거 바르고 해서 나의 자료형에 넣고 (2복사), 여기저기 흐름타고 다니면서 또복사를 하기 쉽다.

이것의 성능을 고도화 하려면 read한 버퍼의 레퍼런스만 들고 다니면서, 컨버전을 회피하면서 처리하면 복사를 줄이고 성능을 올릴 수 있다. read하는 go 루틴이 빠르게 e다음 read를 받을 수 있도록 데이터 작업을 다른 go 루틴으로 떠넘기고 빠져야 할 때가 있는데, 이런 상황이라면 큐잉을 하고 read용 버퍼 재사용을 위해 복사가 필요하다. 그러나 사실은 io 보다는 cpu가 빠르기에 이런저런 뽁짝뽁짝 판타지가 아니라면 최대한 빨리 끝내고 복사고 큐잉이고 없이 다음 read로 가는 방법도 유효하다.

파이썬 할 때도 이 데이터의 실체가 레퍼런스냐 값이냐를 두고 우왕좌왕 했는데 go에서도 조금 우왕좌왕하는 시간을 보낼 것 같다.

스택 오버 플로에도 답변이 있다.

https://stackoverflow.com/questions/14373634/how-expensive-is-bytestring









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