5 분 소요


static link에 대해 알아보았으니 이번엔 dynmaic link에 대해 알아보도록 하겠습니다.


Dynamic library

12 지난 글에서 살펴봤던 static library를 linking하는 경우를 생각해 봅시다. 시간이 지남에 따라 프로그램의 스케일이 커지고 더 많은 라이브러리가 추가되면서 프로그램의 크기도 커질 것입니다. 결국 빌드 과정중에 static linking에 걸리는 시간도 점점 증가한다는 것을 의미합니다.


13 그렇다면 이렇게 바꿔보는 것은 어떨까요? ar을 ld로 변경하였습니다. 그리고 라이브러리의 output또한 executable한 바이너리로 바뀌었습니다. 이게 바로 90년대에 dynamic library가 등장하던 시절의 모습입니다. 줄여서 “dylibs”라고 부르기도 하죠.


14 어떻게 프로그램의 크기를 줄인걸까요? 핵심은 static linker가 dynamic library에 대한 linking을 다르게 처리하는데 있습니다. linker는 dynamic library의 코드를 복사하는 대신 일종의 약속을 세겨넣습니다. dynamic library에서 사용한 symbol 이름과 런타임 시의 라이브러리의 경로를 기록하는 것입니다. 쉽게 말해 dynamic library의 참조를 남깁니다.


이렇게 하면 얻을 수 있는 이점은 무엇일까요? 바로 프로그램의 사이즈를 작게 유지 할 수 있다는 것입니다. 단순히 우리가 작성한 코드와 런타임에 필요한 dynamic library에 대한 정보만 있으면 될 뿐이니까요. 프로그램은 더이상 라이브러리 코드의 복사본을 들고 있을 필요도 없으며, static link 시간은 우리가 작성한 코드의 크기에만 영향을 받을 뿐 얼마나 많은 dylib을 가지고 있는지와는 무관해 집니다.


15 게다가 가상 메모리 시스템을 적극적으로 활용할 수 있는 환경이 갖추어지게 됩니다. 서로 다른 프로세스에서 같은 dynamic library를 사용하면 가상메모리는 RAM의 같은 페이지를 재사용하여 해당 dylib을 사용하는 모든 프로세스가 공유하도록 하는 것입니다.


그렇다면 dynamic library를 사용하는데 드는 비용은 어떤것들이 있을까요? dylib은 프로그램의 빌드 시간을 줄여주는 반면에 launch time을 증가시킵니다. 왜냐하면 launching 과정에서 더이상 하나의 프로그램 파일만을 로드하지 않게 되기 떄문입니다. 모든 dylib도 함께 로드되어 우리의 프로그램과 연결되어야 합니다.

다음으로 dynamic library를 사용하는 프로그램은 페이지 구조가 지저분해 집니다. static library의 경우 linker는 모든 static library의 모든 global들을 executable의 동일한 DATA 페이지에 배치합니다. 하지만 dylib은 라이브러리마다의 DATA페이를 각각 가지고 있습니다.

마지막 비용은 dynamic linker입니다. 프로그램에 남겨놓은 약속을 기억하시나요? 이 약속을 지키기위한 무언가가 런타임에 필요해 지게 됩니다. 그게 바로 dyld, 즉 dynamic linker 입니다.


Best Practice

지금까지 살펴본 dynamic linking의 best practice는 어떻게 될까요? dyld는 이미 최대한으로 가속화되어 있기 때문에 우리가 통제할 수 있는 것은 사요하는 dylib의 수 입니다. dylib이 많아질 수록 dyld의 로드 작업은 많아지므로 적은 수의 dylib만을 사용하길 권장합니다.

static initializer를 제거하거나 최적화 하기시 바랍니다. 특히 static intializer에서는 IO나 networking을 일으키지 않는것이 좋습니다. 몇 ms 보다 올래걸리는 작업은 생성자에서 이루어져서는 안됩니다.

static library와 dynamic library를 사용하는 것 사이에 적절한 지점을 찾기 바랍니다. 너무 많은 static library는 여러분의 개발 속도를 늦추고, 너무 많은 dynamic library는 lauch time을 늘려 사용자 경험을 해칩니다. 올해 이루어진 ld64의 성능 개선으로 인해 두 의존성 사이의 적정점이 더 많은 static library를 사용하는 쪽으로 기울게 될 수도 있을 것입니다.

마지막으로 deployment tartget을 13.4 이상으로 설정함으로써 dyld의 성능 개선(chained fixup / 생략된 부분) 효과를 볼 수 있을 것입니다.



ref.

Link fast: Improve build and launch times