본문 바로가기

시스템 소프트웨어 개발을 위한 Arm 아키텍처의 구조와 원리

[ARM] const static 키워드로 변수를 선언: 코드 크기 최적화

코드를 작성하다보면 배열을 선언한 후 그 값을 상수와 같이 사용할 때가 있습니다.
한 가지 예를 들겠습니다. 다음 코드를 보면 rtw_cfg80211_default_mgmt_stypes 배열은static const  키워드로 선언돼 있습니다.
 
static const struct ieee80211_txrx_stypes
rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_ADHOC] = {
.tx = 0xffff,
.rx = BIT(IEEE80211_STYPE_ACTION >> 4)
},
 
rtw_cfg80211_default_mgmt_stypes 배열은 고정된 값을 저장하고 실행 중에 바뀌지 않습니다.
 
위 코드를 컴파일하고 코드 사이즈를 측정해볼까요? size란 바이너리 유틸리티를 활용해 오브젝트의 사이즈를 확인해봅시다.
 
root@raspberrypi:/home/pi/src/rpi_dev_code# ./aarch64-linux-gnu-size ./out/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.o
   text    data     bss     dec     hex filename
  26046    4888       0   30934    78d6 ./out/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.o
 
 
코드 수정해보기
 
이제 rtw_cfg80211_default_mgmt_stypes  변수에 const 키워드를 빼 보겠습니다.
 
diff --git a/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.c
index 28807e9..a7319d9 100755
diff --git a/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.c
index 28807e9..e641551 100755
--- a/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.c
+++ b/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.c
@@ -246,7 +246,7 @@ void rtw_spt_band_free(struct ieee80211_supported_band *spt_band)
 }
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
-static const struct ieee80211_txrx_stypes
+static struct ieee80211_txrx_stypes
 rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
        [NL80211_IFTYPE_ADHOC] = {
                .tx = 0xffff,
 
위와 같이 코드를 수정한 다음에 빌드를 한 후, size란 바이너리 유틸리티를 활용해 오브젝트의 사이즈를 확인해봅시다.
 
root@raspberrypi:/home/pi/src/rpi_dev_code# ./aarch64-linux-gnu-size ./out/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.o
   text    data     bss     dec     hex filename
  25998    4944       0   30942    78de ./out/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.o
 
결과가 달라졌습니다.
 
오브젝트 사이즈 크기 비교
 
이제 const 키워드가 있을 때와 없을 때 코드 사이즈를 비교해 봅시다.
 
(before)
   text    data     bss     dec     hex filename
  26046    4888       0   30934    78d6 ./out/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.o
 
(after)
   text    data     bss     dec     hex filename
  25998    4944       0   30942    78de ./out/drivers/net/wireless/realtek/rtl8192cu/os_dep/linux/ioctl_cfg80211.o
 
.data 섹션: +66 바이트
.dec  섹션:   +8 바이트
.text 섹션:   -48 바이트
 
오브젝트의 26바이트가 증가 됐습니다.
 
26바이트면 무시할만한 사이즈라 말할 수 있지만, 소형 임베디드 시스템에서는 1K라도 아끼는 최적화 코딩을 해야 합니다.
왜냐면 스택 사이즈도 적고, 파티션 사이즈도 최대한 작은 사이즈으로 구성하는 경우가 많이 때문이죠.
 
이런 코드가 모이면 전체 이미지의 1K, 5K 정도로 크기가 증가할 수 있으니, 이 팁을 잘 활용하면 좋을 것 같습니다. 
 
 
리눅스 커널 커뮤니티에서 유사한 패치가 보이니, 아래 내용도 참고하면 좋겠네요.
 
From: Colin Ian King <colin.king@canonical.com>
 
Arrays pwr_info_offset and sprom_sizes can be make static const rather
than populating them on the stack. Shrinks object size by 236 bytes.
 
Before:
   text    data     bss     dec     hex filename
  11300    1320      64   12684    318c drivers/bcma/sprom.o
 
After:
   text    data     bss     dec     hex filename
  10904    1480      64   12448    30a0 drivers/bcma/sprom.o
 
 
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 206edd3ba668..bd2c923a6586 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -222,7 +222,7 @@  static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
 {
  u16 v, o;
  int i;
- u16 pwr_info_offset[] = {
+ static const u16 pwr_info_offset[] = {
  SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
  SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
  };
@@ -578,9 +578,11 @@  int bcma_sprom_get(struct bcma_bus *bus)
 {
  u16 offset = BCMA_CC_SPROM;
  u16 *sprom;
- size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4,
-  SSB_SPROMSIZE_WORDS_R10,
-  SSB_SPROMSIZE_WORDS_R11, };
+ static const size_t sprom_sizes[] = {
+ SSB_SPROMSIZE_WORDS_R4,
+ SSB_SPROMSIZE_WORDS_R10,
+ SSB_SPROMSIZE_WORDS_R11,
+ };
  int i, err = 0;
 
  if (!bus->drv_cc.core)
 
커밋 메시지를 보니 무려 236 바이트나 절약됐다고 하네요.
 
---
"이 포스팅이 유익하다고 생각되시면 공감 혹은 댓글로 응원해주시면 감사하겠습니다. 
"혹시 궁금한 점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실히 답변 올려드리겠습니다!"
 
​Thanks,
Guillermo Austin Kim(austindh.kim@gmail.com)
---