Default vs Release build in Crystal

Crystal은 컴파일 언어로 바이너리로 빌드하여 사용할 수 있습니다. 그리고 공식 가이드에선 release build 시 —release flag 사용을 권고하고 있는데요. 오늘은 이 flag가 어떤 역할을 하는지, 왜 권고되고 있는지 정리해봅니다.

By default, the generated executables are not fully optimized. The –release flag can be used to enable optimizations. Crystal-lang

Make empty app

Default와 –release flag는 어떤 차이를 가질지 궁금하기 때문에 간단하게 빈 앱을 만들어 테스트를 해보겠습니다.

# 테스트 앱 생성
crystal init app sizetest
cd sizetest
# Build command for Default mode
shards build

# Build command for Release mode
shards build --release --no-debug

Diff

Build Speed

최적화 과정이 생략되기 때문에 아무런 flag 없이 빌드하는 것이 더 빠릅니다.

  • default: 1.1s
  • release: 6.8s

Size

실제 Output의 크기는 생각보다 많이 차이납니다.

-rwxr-xr-x  1 hahwul  hahwul   1.3M Mar 21 01:56 sizetest
# build no flag

-rwxr-xr-x  1 hahwul  hahwul   256K Mar 21 01:57 sizetest
# build with --release --no-debug

Symbol

심볼도 최적화 대상에 포함되는 것 같습니다. 많이 줄어듭니다.

nm bin/sizetest | wc -l
# => 2593
# build no flag

nm bin/sizetest | wc -l
# => 448
# build with --release --no-debug

Speed

속도는 단순히 빈 앱으로 비교해보기 어렵기 때문에 알려진 벤치마크 사이트에서 사용한 코드를 이용해보려고 합니다. 벤치마크는 cli에 대한 벤치마크 도구인 hyperfine을 이용합니다.

결과는 아래와 같습니다. 속도가 조금 차이가 날거라곤 생각했지만, 엄청난 차이가 발생했네요.

  • default: 7.064 s ± 0.026 s
  • release: 641.9 ms ± 0.9 ms

Conclusion

요약하자면 –release flag를 붙이는 경우 용량, 속도 등에서 모두 이점을 가지고 빌드 시간만 살짝 늘어납니다. 공식 가이드의 언급대로 개발 과정에선 기본 옵션이 빠른 빌드로 인해 편리할 것으로 보이고, 실제 배포나 테스트 등에선 무조건 릴리즈 빌드로 만드는게 맞을 것 같습니다.

애매하다면 릴리즈 빌드를 만드는걸 기본으로 사용하는 방법도 좋아보이네요 :D

References