닷넷에 네이티브 AOT같은 경우에는 프로젝트 전체가 전부 기계어로 빌드된다.
그런데 지난번 언급처럼 이렇게 되면 프로그래밍 기법이 전부 바뀌어야 한다.
리플렉션 DI 제네릭심화 다이나믹 키워드 같은 경우는 들어가면
빌드가 안되어 버린다.
빌드가 안되어 버린다.
그렇다면 기계어로 구워지는게 안되는것이냐 하겠지만..
이 경우에도 기계어로 빌드될수 있도록 배포/빌드하는 기능이 하나있다.
바로 ReadyToRun (R2R) 기능이다.
일반적으로 C#닷넷은 중간언어로 빌드되어 런타임에 프레임워크가
소스코드를 해석해서 기계어로 변형되어 실행된다. 이 과정의 오버헤드가 높다.
그런데 R2R은 배포 빌드를 할때 영리한 전략을 쓰는데..
가상머신이 실행중에 JIT 컴파일러로 해야 할 일을 빌드시점에 미리 대신해서
그 결과물인 기계어를 중간 언어(IL)와 함께 빌드해 버린다.
물론 AOT처럼 깡 기계어로 되는게 아니라 중간 언어가 노출되어 버리는건
똑같지만 이정도만 하더라도 초기 로딩속도는 나름 빨라진다.
일단 메모리에 올라가면 JIT나 AOT나 속도는 비슷비슷하다.
그래서 메모리에 올라가서 JIT가 해석하는 시간이 관건인것이다.
그리고 기계어로 변환될지 말지를 결정하는 단위는 함수단위 이다.
함수단위로 분석을 해서 파라미터 본문 리턴값을 바라볼때 자료크기나 자료형이
예측 가능하다면 기계어로 구워지고 DI나 리플렉션 제네릭처럼 런타임에 크기나
자료형이 결정되어 지거나 이러한 함수들은 그냥 JIT에 의존을 하도록 변경된다.
따라서 최초 실행되거나 실행중 동적라이브러리 (DLL) 로딩을 하거나 이러는 경우도
대상이 되므로 빌드시점에 이것들이 기계어로 바뀔지 말지가 결정이 된다.
주의 할점이 있는데 배포(Publish) 단계에서 컴파일러가 판단해서 이것은
잘라내도 된다고 판단해서 코드가 잘라내어 지면(Trimmed) 실행중에 실제로
잘라내도 된다고 판단해서 코드가 잘라내어 지면(Trimmed) 실행중에 실제로
해당코드가 없어서 낭패를 볼 수가 있으므로 용량이 조금 늘어나더라도
*.csproj 에서 프로젝트 그룹에 다음처럼
<PublishTrimmed>false</PublishTrimmed>
배포시 Trim기능 사용안함으로 하고 빌드하는것이 정신건강에 이롭다.
이렇게 해서 R2R 옵션으로 빌드하면 초기 로딩속도가 상당히 빨라지고
실행중간에 예측불가능한 부분을 만나면 JIT에 의존해서 돌아가고
나머지는 그냥 JIT가 해야할일이 기계어로 빌드된것이 실행된다.
AOT와 R2R의 근본적인 차이는
R2R은 JIT 컴파일러가 미래에 해야 할일을 빌드 시점에 미리 대신해서 찔러 넣어둔 것이고,
AOT는 가상머신이건 뭐건 다 걷어치우고 프로그램과 함수 구조 그 자체를 순수
C/C++ 프로그램처럼 깡기계어로 빌드한 결과물이라고 할수 있다.
따라서 R2R로 빌드해서 기계어가 일부 들어간다고 해서 AOT처럼 기계어수준의
난독화가 되는것이 아니고 중간언어가 함께 들어가기 때문에 보안이 좋다는
착각을 해서는 안된다.
난독화가 되는것이 아니고 중간언어가 함께 들어가기 때문에 보안이 좋다는
착각을 해서는 안된다.
댓글 없음:
댓글 쓰기