programing

정적 링크와 동적 링크

javaba 2022. 8. 27. 21:59
반응형

정적 링크와 동적 링크

특정 상황에서 동적 링크 대신 정적 링크를 선택해야 하는 설득력 있는 성능 이유가 있습니까?나는 다음과 같은 것을 듣거나 읽었지만, 그 주제에 대해서는 그 진실성을 보증할 만큼 충분히 알지 못한다.

1) 정적 링크와 동적 링크의 런타임 성능 차이는 보통 무시할 수 있습니다.

2) (1) 프로파일 데이터를 사용하여 프로그램 핫패스를 최적화하는 프로파일링 컴파일러를 사용하면 컴파일러가 코드와 라이브러리 코드를 모두 최적화할 수 있기 때문에 사실이 아닙니다.동적 링크를 사용하면 코드만 최적화할 수 있습니다.대부분의 시간을 라이브러리 코드를 실행하는 데 사용할 경우 큰 차이가 발생할 수 있습니다.그렇지 않으면 (1)이 계속 적용된다.

  • 동적 링크는 리소스 총 소비량을 줄일 수 있습니다(여러 프로세스가 동일한 라이브러리를 공유하는 경우(물론 "같은" 버전 포함).나는 이것이 대부분의 환경에서 그 존재감을 이끄는 주장이라고 믿는다.여기서 "리소스"에는 디스크 공간, RAM 및 캐시 공간이 포함됩니다.물론 다이내믹링커가 충분히 유연하지 않으면 DLL Hell의 위험이 있습니다.
  • 동적 링크란 버그 수정 및 라이브러리 업그레이드를 전파하여 제품을 개선하여 출하할 필요가 없음을 의미합니다.
  • 플러그인은 항상 동적 링크를 호출합니다.
  • 정적 링크란 매우 제한된 환경(부트 프로세스 초기 또는 복구 모드)에서 코드가 실행됨을 알 수 있음을 의미합니다.
  • 정적 링크로 바이너리를 다양한 사용자 환경에 보다 쉽게 배포할 수 있습니다(대규모의 자원을 필요로 하는 프로그램을 보내는 비용).
  • 정적 링크로 인해 부팅 시간이 다소 단축될 수 있지만, 이는 프로그램의 크기와 복잡성, 그리고 OS의 로드 전략의 세부 사항에 따라 어느 정도 달라집니다.

일부 편집은 매우 관련성이 높은 제안을 코멘트 및 기타 답변에 포함시킵니다.이 문제를 해결하는 방법은 어떤 환경에서 실행할지에 따라 크게 다르다는 점에 유의하십시오.최소한의 임베디드 시스템에서는 동적 링크를 지원하기에 충분한 리소스가 없을 수 있습니다.약간 큰 소형 시스템은 메모리가 작기 때문에 동적 링크에 의한 RAM 절감 효과가 매우 매력적이기 때문에 동적 링크를 충분히 지원할 수 있습니다.본격적인 소비자용 PC는 Mark가 지적한 와 같이 막대한 자원을 보유하고 있으며, 편의상의 문제로 인해 이 문제에 대한 생각을 주도할 수 있습니다.


퍼포먼스와 효율의 문제에 대처하는 방법: 상황에 따라 다릅니다.

일반적으로 동적 라이브러리에는 함수 어드레싱에서 이중 디스패치 또는 추가 간접 레이어가 필요하며 약간의 비용이 들 수 있습니다(그러나 함수 호출 시간이 실제로 실행 시간의 큰 부분을 차지합니까?).?).

다만, 같은 라이브러리를 많이 호출하는 복수의 프로세스를 실행하고 있는 경우는, 스태틱 링크를 사용하는 것에 비해, 동적 링크를 사용하면 캐시 라인을 절약할 수 있어 퍼포먼스를 향상시킬 수 있습니다(현대의 OS는, 스태틱 링크 바이너리에서 같은 세그먼트를 인식할 수 있을 정도로 스마트하지 않습니다).어려운 것 같은데, 아는 사람 있어?

또 다른 문제는 로드 시간입니다.적재 비용은 어느 시점에 지불합니다.이 비용을 지불할 때는 OS의 동작 방법 및 사용하는 링크에 따라 달라집니다.필요할 때까지 지불을 미루는 게 나을 수도 있어요.

static-vs-dynamic 링크는 모두 오브젝트 파일까지 개별 컴파일이 필요하기 때문에 일반적으로 최적화 문제가 아닙니다.단, 컴파일러는 원칙적으로 처음에 요약된 AST 형식으로 "정적 라이브러리"를 "컴파일"하고 이러한 AST를 메인 코드용으로 생성된 AST에 추가하여 이들을 "링크"할 수 있으므로 글로벌 최적화가 가능합니다.사용하고 있는 시스템 중 어느 것도 이 기능을 하지 않기 때문에, 그 동작에 대해서는 코멘트할 수 없습니다.

퍼포먼스에 관한 질문에 대한 답변은 항상 테스트(및 가능한 한 도입 환경과 같은 테스트 환경을 사용)를 통해 이루어집니다.

Static linking는 링크된 콘텐츠가 프라이머리 바이너리로 복사되어 단일 바이너리가 되는 컴파일 시간 프로세스입니다.

단점:

  • 컴파일 시간이 길다
  • 출력 바이너리가 더 큼

Dynamic linking는 링크된 콘텐츠가 로드될 때 실행 시 프로세스입니다.이 기술에는 다음이 포함됩니다.

  • 기본 바이너리를 다시 컴파일하지 않고 링크된 바이너리를 업그레이드하여ABI안정[About].
  • 1개의 공유 복사가 있습니다.

단점:

  • 시작 시간이 느리다(링크된 콘텐츠를 복사해야 함)
  • 링커 오류가 런타임에 느려진다.

[iOS 정적 프레임워크 vs 다이내믹 프레임워크]

1) DLL 함수를 호출하면 항상 추가 간접 점프를 사용한다는 사실에 기초합니다.오늘날, 이것은 보통 무시할 수 있는 것입니다.위치 독립 코드를 생성할 수 없기 때문에 DLL 내부에는 i386 CPU의 오버헤드가 약간 더 있습니다.amd64에서는 점프는 프로그램 카운터에 비례할 수 있기 때문에 크게 향상되었습니다.

2) 이것이 맞습니다.프로파일링을 통해 최적화를 유도하면 보통 10~15%의 성능을 얻을 수 있습니다.이제 CPU 속도가 한계에 도달했으므로 이 작업을 수행할 가치가 있습니다.

덧붙입니다. (3) 링커는 캐시 효율이 높은 그룹으로 함수를 배열하여 고가의 캐시 레벨 미스를 최소화할 수 있습니다.또, 특히 애플리케이션의 기동 시간에 영향을 주는 경우가 있습니다(Sun C++ 컴파일러로 본 결과에 근거합니다).

또한 DLL을 사용하면 데드 코드를 제거할 수 없습니다.언어에 따라서는, DLL 코드도 최적이 아닌 경우가 있습니다.컴파일러는 클라이언트가 가상 함수를 덮어쓰고 있는지 여부를 인식하지 못하기 때문에 가상 함수는 항상 가상입니다.

이러한 이유로 DLL이 실제로 필요하지 않은 경우 정적 컴파일을 사용합니다.

EDIT(댓글에 응답하려면 사용자 밑줄 사용)

다음은 위치 독립 코드 문제에 대한 유용한 리소스입니다.http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/

설명한 바와 같이 x86에는 AFIK가 없고 15비트 점프 범위 이외에는 무조건 점프 및 콜이 없습니다.그렇기 때문에 (발전기에서 나오는) 함수는 항상 문제가 되어 매립형 트램펄린이 필요했습니다.

그러나 Linux와 같은 일반적인 x86 OS에서는 .so/DLL 파일이 생성되지 않은 경우gcc전환하다-fpic(간접 점프 테이블 사용을 강제합니다).그렇지 않으면 일반 링커처럼 코드가 고정되기 때문입니다.그러나 이 작업을 수행하는 동안 코드 세그먼트를 공유할 수 없게 되어 디스크에서 메모리로 코드를 완전히 매핑하고 모든 것을 터치해야 사용할 수 있습니다(대부분의 캐시를 허용하거나 TLB를 누르거나).이것이 느리다고 여겨지던 시절이 있었다.

그래서 당신은 더 이상 혜택을 받지 못할 것입니다.

어떤 OS(Solaris 또는 FreeB)가 기억나지 않는다.SD)를 사용하면 Unix 빌드 시스템에 문제가 생깁니다.그 이유는 이 작업을 하지 않았기 때문인데, 이 시스템을 적용하기 전까지는 왜 크래쉬가 일어났는지 궁금했기 때문입니다.-fPIC로.gcc.

동적 링크는 LGPL과 같은 몇 가지 라이센스 요건을 충족하는 유일한 실용적인 방법입니다.

정적 링크에는 프로그램에 필요한 파일이 단일 실행 파일에 포함됩니다.

동적 링크는 일반적인 것으로 간주됩니다.이것은 DLL을 필요로 하는 실행 파일을 같은 디렉토리(또는 DLL이 시스템폴더에 있는 경우가 있습니다)에 만듭니다.

(DLL = 동적 링크 라이브러리)

동적으로 연결된 실행 파일은 컴파일 속도가 빨라 리소스 부담이 적습니다.

나는 dnmckey가 언급한 점들과 더불어 다음과 같은 점들에 동의한다.

  • 정적으로 링크된 응용 프로그램이 없거나 잘못된 위치에 설치되었을 때 문제를 일으킬 수 있는 추가 파일 종속성(.dll/.so)이 적거나 전혀 없기 때문에 배포가 더 쉬울 수 있습니다.

정적으로 링크된 빌드를 실행하는 이유 중 하나는 실행 파일을 완전히 닫았는지, 즉 모든 심볼 참조가 올바르게 확인되었는지 확인하는 것입니다.

연속적인 통합을 사용하여 구축 및 테스트하고 있던 대규모 시스템의 일부로서 야간 회귀 테스트는 정적 링크 버전의 실행 파일을 사용하여 실행되었습니다.동적으로 링크된 실행 파일이 정상적으로 링크되어도 심볼이 해결되지 않고 스태틱링크에 장애가 발생할 수 있습니다.

이는 보통 공유 libs 내에 깊숙이 자리 잡은 심볼에 이름이 잘못 입력되어 정적으로 링크되지 않을 때 발생합니다.깊이 우선 평가 또는 폭 우선 평가 사용에 관계없이 동적 링커는 모든 기호를 완전히 해결하지 않으므로 완전히 닫히지 않은 동적으로 연결된 실행 파일로 마무리할 수 있습니다.

동적 링크의 가장 좋은 예는 라이브러리가 사용된 하드웨어에 종속되어 있는 경우입니다.고대에는 각 플랫폼이 모든 프로세서 기능을 사용하여 최적화할 수 있도록 C 연산 라이브러리는 동적이라고 결정되었습니다.

더 좋은 예로 OpenGL을 들 수 있습니다.OpenGl은 AMD와 NVidia에 의해 다르게 구현되는 API입니다.또한 하드웨어가 다르기 때문에 AMD 카드에서는 NVidia 구현을 사용할 수 없습니다.따라서 OpenGL을 프로그램에 정적으로 링크할 수 없습니다.여기서는 API를 모든 플랫폼에 최적화하기 위해 동적 링크를 사용합니다.

동적 링크를 사용하려면 OS가 동적 라이브러리를 검색하여 로드하는 데 시간이 더 필요합니다.정적 링크에서는 모든 것이 하나로 되어 메모리에 대한 원샷 로드입니다.

DLL Hell도 참조하십시오.이것은 OS가 로드하는 DLL이 응용 프로그램과 함께 제공된 DLL 또는 응용 프로그램이 예상하는 버전이 아닌 시나리오입니다.

아직 논의되지 않은 또 다른 문제는 라이브러리의 버그를 수정하는 것입니다.

정적 링크에서는 라이브러리를 재구축해야 할 뿐만 아니라 실행 파일을 다시 링크하고 재배포해야 합니다.라이브러리가 하나의 실행 파일로만 사용되는 경우 문제가 되지 않을 수 있습니다.그러나 재링크 및 재배포해야 하는 실행 파일이 많을수록 더 큰 문제가 발생합니다.

동적 링크를 사용하면 동적 라이브러리를 재구축 및 재배포하기만 하면 됩니다.

정말 간단해.소스 코드를 변경할 때 10분 동안 기다리시겠습니까, 아니면 20초 동안 기다리시겠습니까?20초밖에 못 참아요.그 이상으로 칼을 꺼내든가 아니면 어떻게 하면 편찬과 연계로 다시 안전지대로 되돌릴 수 있을까를 생각하기 시작합니다.

정적 링크 수준이 애플리케이션 및 시스템 성능에 매우 긍정적인 영향을 미칠 수 있는 시스템은 방대하고 증가하고 있습니다.

저는 흔히 '임베디드 시스템'이라고 불리는 것을 언급합니다.이것들 중 상당수는 현재 범용 운영체제를 점점 더 많이 사용하고 있으며, 이러한 시스템은 상상할 수 있는 모든 것에 사용되고 있습니다.

일반적인 예로는 Busybox를 사용하는 GNU/Linux 시스템을 사용하는 디바이스가 있습니다.커널과 루트 파일 시스템을 모두 포함하는 부팅 가능한 i386(32비트) 시스템 이미지를 구축함으로써 NetBSD를 통해 이 문제를 극단적으로 해결했습니다.이러한 이미지는 커널과 루트 파일 시스템을 모두 포함하고 있습니다.후자는 단일 스태틱 링크를 포함하고 있습니다.crunchgen) 바이너리에는 표준 풀 기능 시스템 프로그램(툴 체인 제외)을 모두 포함하는 모든 프로그램(최종 274개)에 대한 하드 링크가 포함되어 있으며, 크기는 20MB 미만입니다(또한 64MB의 메모리(루트 파일 시스템 전체가 압축되지 않은 상태에서도 RAM에 있는 시스템에서도 매우 쾌적하게 동작합니다).h 테스트할 수 있는 작은 것을 찾을 수 없었습니다.)

이전 게시물에서는 정적 링크 바이너리의 시작 시간이 더 빠르다고 언급했지만(또한 훨씬 더 빠를 수 있습니다), 이는 그림의 일부일 뿐이며, 특히 모든 오브젝트 코드가 동일한 파일에 링크되어 있는 경우, 운영 체제가 실행 파일에서 직접 페이징 코드를 요구하는 것을 지원하는 경우에는 더욱 그렇습니다.이 이상적인 시나리오에서는 거의 모든 코드 페이지가 이미 메모리에 저장되어 셸에 의해 사용되고 있기 때문에 프로그램의 기동 시간은 문자 그대로 무시할 수 있습니다.init실행 중일 수 있는 다른 백그라운드 프로세스)는 프로그램의 런타임 요건을 충족하기 위해 메모리의 한 페이지만 로드하면 되기 때문에 부팅 후 요청된 프로그램이 실행되지 않은 경우에도 마찬가지입니다.

그러나 그것이 여전히 전부는 아니다.또, 통상, 모든 바이너리를 스태틱 링크 하는 것으로써, 완전한 개발 시스템의 NetBSD operating system의 인스톨을 구축해 사용하고 있습니다.이 작업에는 엄청난 디스크 공간(툴 체인 및 X11 정적 링크 포함 모든 것을 포함한 x86_64의 경우 총 6.6GB까지)이 소요됩니다(특히 모든 프로그램에서 완전한 디버깅 기호 테이블을 사용할 수 있는 경우 2.5까지).GB)의 결과는 여전히 전체적으로 더 빠르게 실행되며 일부 태스크에서는 라이브러리 코드 페이지를 공유하는 것을 가장하는 일반적인 동적 링크 시스템보다 더 적은 메모리를 사용합니다.디스크는 저렴하고(고속 디스크도 가능), 자주 사용하는 디스크 파일을 캐싱하는 메모리도 비교적 저렴하지만 CPU 사이클은 그렇지 않습니다.ld.so기동할 때마다 기동하는 프로세스의 기동 코스트는, 특히 개발 시스템의 컴파일러 등, 같은 프로그램을 몇번이나 반복해 사용하고 있는 경우에는, 많은 프로세스를 기동할 필요가 있는 태스크로부터 몇시간씩의 CPU 사이클이 필요하게 됩니다.정적 연동 툴 체인 프로그램을 사용하면 전체 OS 멀티 아키텍처 구축 시간을 몇 시간 단축할 수 있습니다.아직 툴체인을 싱글로 만들지 않았습니다.crunchgen'ed binary, 하지만 그렇게 하면 CPU 캐시가 성공하기 때문에 빌드 시간이 더 절약될 것으로 예상됩니다.

정적 링크는 프로그램 전체를 다시 컴파일해야 하는 변경을 위해 단일 exe만 제공합니다.동적 링크에서는 dll만 변경해야 하며 exe를 실행할 때 변경 내용은 실행 시 선택됩니다.동적 링크(Windows 등)를 통해 업데이트 및 버그 수정을 쉽게 제공할 수 있습니다.

Unix와 유사한 시스템에서는 동적 링크로 인해 'root'이 외부 위치에 설치된 공유 라이브러리와 함께 애플리케이션을 사용하는 것이 어려워질 수 있습니다.이는 동적 링커가 일반적으로 루트 권한을 가진 프로세스에서는 LD_LIBRARY_PATH 또는 이와 동등한 것에 주의를 기울이지 않기 때문입니다.그러면 스태틱 링크로 위기를 모면할 수 있습니다.

또는 설치 프로세스에서 라이브러리를 찾아야 하지만 여러 버전의 소프트웨어가 머신에서 공존하기 어려울 수 있습니다.

1/ 다이내믹 링크와 스태틱 링크의 벤치마크에 의해 그 차이를 충분히 작게 판단하지 않고 다이내믹 링크로 전환한 프로젝트 (테스트의 일부가 아니라 결론만 알고 있습니다)

2/ 동적 링크는 PIC(Position Independent Code, 로딩되는 주소에 따라 변경할 필요가 없는 코드)와 관련된 경우가 많습니다.아키텍처에 따라서는 PIC는 또 다른 속도 저하를 가져올 수 있지만, 2개의 실행 가능 파일(OS가 보안 대책으로서 로드 주소의 랜덤화를 사용하는 경우는 같은 실행 가능 파일의 2개의 프로세스도 포함) 간에 동적으로 링크된 라이브러리를 공유하는 이점을 얻기 위해 필요합니다.모든 OS가 두 가지 개념을 분리할 수 있는지는 확실하지 않지만 Solaris와 Linux는 분리할 수 있고 HP-UX는 ICR도 분리할 수 있습니다.

3/ 다른 프로젝트에서는 "간단한 패치" 기능을 위해 동적 링크를 사용한 적이 있습니다.그러나 이 "간단한 패치"로 인해 작은 수정 프로그램의 배포가 조금 더 쉬워지고 복잡한 수정 프로그램의 배포는 악몽이 됩니다.잘못된 버전이 토큰이기 때문에 고객 사이트에서 문제를 추적해야 하는 것 외에 모든 것을 밀어붙여야 하는 경우가 많았습니다.

결론은 다음과 같은 경우를 제외하고 정적 링크를 사용했다는 것입니다.

  • 동적 링크에 의존하는 플러그인 등

  • 공유가 중요한 경우(C/C++ 런타임, GUI 라이브러리 등 여러 프로세스에 의해 동시에 사용되는 큰 라이브러리, 자주 독립적으로 관리되며 ABI가 엄격하게 정의됨)

"간단한 패치"를 사용하려면 위의 큰 라이브러리처럼 라이브러리를 관리해야 합니다. 라이브러리는 수정에 의해 변경되어서는 안 되는 정의된 ABI와 거의 독립적이어야 합니다.

또 하나의 고려사항은 라이브러리에서 실제로 사용하는 오브젝트 파일(변환 유닛)의 수와 사용 가능한 총 수입니다.라이브러리가 여러 개체 파일로 구성되었지만 일부 개체 파일의 기호만 사용하는 경우 정적 링크(일반적으로)에 사용하는 개체만 링크하고 사용되지 않는 기호는 일반적으로 전송하지 않으므로 정적 링크를 선호할 수 있습니다.공유 lib를 사용하는 경우 해당 lib에는 모든 변환 유닛이 포함되어 있으며 필요한 것보다 훨씬 커질 수 있습니다.

언급URL : https://stackoverflow.com/questions/1993390/static-linking-vs-dynamic-linking

반응형