이 블로그는 John Bentley의 동명(Programming Perals)서적을 읽던도중 시작이 되었기에 여기에 실린 주옥같은 내용을 실어보도록 하자.
우리가 주로 접하는 32비트 범용레지스터 크기를 가진 프로세서들은 성능을 위해 메모리 접근를 최소화할뿐 아니라 한번에 많은 메모리정보를 얻기위해 4바이트의 배수이길 갈구한다.
때문에 컴파일러 역시 기본적으로 데이타를 4의 배수로 나열하려는 욕심을 가지고 있다.
컴파일러들은 최적화라는 사명아래 기본적으로 구조체 내에서 가장 크기가 큰 타입을 기준으로 삼는다.
예를 들어 int, char 멤버가 있다면 int를 기준으로 하여 4(x64 라면 8바이트)바이트로 팩 하려 든다. 혹자를 이를 낭비라고 하지만, 이는 성능을 위한 컴파일러의 선택이며 #pragma pack 키워드를 통해 프로그래머가 강제할 수 있도록 지원하고 있다.
노련한 프로그래머라면 구조체 멤버의 순서 바꾸기를 통해서 팩없이 해결할수도 있을 것이다. - 그냥 성능보다는 편안함을 추구한다면 구조체를 1바이트로 팩할수도 있다. 소켓 통신용 프로토콜을 디자인하는경우 흔히 사용한다.
테스트 결과 매우 유동적인 메모리 할당 방식을 확인할수있다.
필자의 PC에서는 12바이트 구조체를 연속으로 new 했을경우 리턴된 포인터의 간격이 56바이트나 차이났다.
결국 12 바이트를 할당해 달라고 했는데 내부적으로 malloc 를 사용해 56바이트나 할당해 44바이트를 낭비하고 있다. 왜 이런 낭비를 부추길까?
디버거를 통해 확인해 보면 malloc()이 호출될때 마다 리턴되는 주소의 앞에 데이타를 변경하는것을 볼수있다. malloc()에 의해 리턴되는 포인터의 위치가 데이타 바디라면 그 앞쪽에는 우리가 모르는 헤더정보가 있는 셈이다.
리턴된 포인터의 16바이트 앞쪽을 조사해 보면 0x00000c 필드도 찾아볼수있다. 즉 12바이트를 할당했다는것을 내부적으로 기록하고 있다. - delete 할때 이 정보가 필요할 것이다!
또한 CPU의 빠른 접근을 위해서 4의 배수로 할당하는것이 현명하므로 리턴되는 주소값이 항상 8바이트의 배수인것을 확인해 볼수있다. 결국 내부적으로 malloc()을 호출하면서 리턴되는 주소의 앞에 특정정보를 기록하기 위해 항상 어느정도의 공간을 남겨놓아야 한다.
자세히 살펴보면 추가되는 공간이 최소한 48바이트며, 그 보다 크거나 작다면 8바이트의 배수를 맞추기 위해 패딩을 실시하는것을 볼수있다. 결국 1바이트를 new 하더라도 내부적으로 48바이트를 할당하게 된다. - 컴파일러에 따라 다를수있다
- TCP/IP 프로토콜에서도 이런 패딩 기법을 사용한다. 만약 자신이 어떠한 프로토콜을 디자인해야 한다면 하드웨어의 사랑을 받기위해서라도 이런 팩, 정렬, 패딩을 고려해야 한다.
2006년 11월 12일
피드 구독하기:
댓글 (Atom)
시리우스 라이브러리 홈페이지 오픈
현재 시리우스(Sirius) 라이브러리라는 제품을 개발하고 이를 소개하는 홈페이지를 오픈 하였습니다. 관심있는 분들의 많은 방문 요청드립니다. 앞으로 업데이트 소식및 변경사항은 스파이럴랩 홈페이지를 통해 진행할 예정입니다. 스파이럴랩 홈페이지 : h...
-
밤 문화를 좋아하신다면 현란한 레이져 쑈(laser show)를 생각할수도 있고, 철판을 자르거나, 반도체 칩 위에 순식간에 글자를 새기는 것을 보신적이 있나요? 이 원리는 레이저라는 매우 순도높은(?) 빛을 발생시키고, 이 ...
-
최근 새롭게 출시된 스캔랩(Scanlab)사의 RTC6를 소개해 드리겠습니다. 관련 메뉴얼을 파악해 본바에 따르면 다음과 같은 기술들이 변경되었네요, 1. 외형을 보면 알수있듯이 PCI express 방식과 함께 Ethernet 통신 타...
-
SCANLAB 사의 RTC 제품들을 사용해 정밀한 레이저 가공을 위해서는 필히 스캐너의 왜곡을 보정해서 사용해야 합니다. 왜곡이 발생되는 이유는 - X, Y 라는 두개의 반사거울의 각도를 돌리면 서로간의 거리가 각도에 따라 변하고, - 빛을 초점...
댓글 없음:
댓글 쓰기