컴파일 제어와 검사

컴파일 제어와 검사

Racket 프로그램과 표현식은 자동으로 그리고 그때그때(온더플라이) 컴파일돼요. raco make 도구(「raco make: 소스를 바이트코드로 컴파일하기」 참고)는 Racket 모듈을 컴파일된 ".zo" 파일로 만들 수 있지만, 그런 사전(ahead-of-time) 컴파일은 단지 프로그램이 더 빨리 시작되도록 해줄 뿐, Racket 프로그램의 실행 성능에는 영향을 주지 않아요.

이 절에서는 컴파일 모드와 컴파일 패스 검사에 대해 다뤄요.

출처: Racket Reference

본문

컴파일 모드

모든 Racket 변종은 머신 독립적인 컴파일 모드를 가정하며, 이 모드는 모든 플랫폼의 모든 Racket 변종에서 동작하는 컴파일된 ".zo" 파일을 생성해요. 머신 독립 컴파일 모드를 선택하려면 current-compile-target-machine 파라미터를 #f로 설정하거나, 시작 시 --compile-any/-M 플래그를 지정하면 돼요. 자세한 내용은 current-compile-target-machine을 참고해요.

그 외의 컴파일 모드는 Racket 구현에 따라 달라져요(「Implementations」 참고).

BC 컴파일 모드

Racket의 BC 구현은 두 가지 컴파일 모드를 지원해요: 바이트코드와 머신 독립 모드. 바이트코드 형식도 BC 구현의 Racket에 대해 모든 운영체제에서 동일하게 동작한다는 의미에서 머신 독립적이지만, Racket의 CS 구현에서는 동작하지 않아요.

바이트코드는 런타임 시 다시 머신 코드로 컴파일되는데, JIT 컴파일러가 비활성화되어 있지 않다면 그래요. eval-jit-enabled를 참고해요.

CS 컴파일 모드

Racket의 CS 구현은 여러 컴파일 모드를 지원해요: 머신 코드, 머신 독립, 해석(interpreted), 그리고 JIT. 머신 코드가 기본 모드이고, 머신 독립 모드는 BC와 동일해요. 해석 모드는 컴파일 없이 코어 링클릿(linklet) 형식 수준에서 인터프리터를 사용해요. JIT 모드는 개별 함수 형식의 컴파일을 요청이 있을 때(on demand) 트리거해요.

기본 모드는 머신 코드와 해석 모드의 하이브리드이며, 해석 모드는 특히 큰 링클릿의 바깥쪽 윤곽(outer contour)에만 사용되고, 머신 코드 모드는 그 바깥 윤곽 안에서 충분히 작은 함수들에 사용돼요. "충분히 작은"은 PLT_CS_COMPILE_LIMIT 환경 변수로 결정되며, 기본값 10000은 대부분의 Racket 모듈이 해석된 구성 요소를 갖지 않는다는 뜻이에요. #%declare#:unlimited-compile 옵션은 둘러싼 모듈에 대해 해석 모드를 비활성화해요. PLT_CS_COMPILE_LIMIT에 의해 컴파일이 더 작은 함수로 제한되는 시점을 알아보려면 'linklet 주제의 'info 로깅을 확인해요(예: PLTSTDERRinfo@linklet로 설정).

JIT 컴파일 모드는 시작 시 PLT_CS_JIT 환경 변수가 설정된 경우에만 사용되고, 그 외에는 시작 시 PLT_CS_INTERP가 설정된 경우에만 순수 해석 모드가 사용되며, PLT_CS_MACH가 설정되고 PLT_CS_JIT가 설정되지 않았거나 그 어떤 환경 변수도 설정되지 않은 경우에는 기본 하이브리드(머신 코드 + 해석) 모드가 사용돼요. 어떤 모드로 컴파일된 모듈이든 현재 컴파일 모드와 무관하게 Racket의 CS 변종에 로드될 수 있어요.

PLT_CS_DEBUG 환경 변수는 「Debugging」에서 설명하듯 머신 코드 모드에서의 컴파일에만 영향을 줘요. PLT_CS_DEBUG가 활성화되면 생성되는 머신 코드가 훨씬 커지지만, 성능에는 그 외의 영향이 없어요.

컴파일러 패스 검사

시작 시 PLT_LINKLET_SHOW 환경 변수가 설정되면, Racket 프로세스의 표준 오류(stderr)에 Racket 형식이 컴파일될 때마다 중간 컴파일된 형식들이 표시돼요. 모든 Racket 변종에 대해, 출력은 원래 Racket 형식에서 생성된 하나 이상의 링클릿을 보여줘요.

Racket의 CS 구현에서는 링클릿을 Chez Scheme 프로시저 형식으로 변환한 "스케미파이드(schemified)" 버전의 링클릿도 함께 표시돼요. 출력은 또한 컴파일러가 작업 중인 모듈과 링클릿이 무엇인지도 알려줘요.

다음 환경 변수들은 PLT_LINKLET_SHOW를 암시하며, 추가적인 중간 컴파일 형식을 보여주거나 형식이 표시되는 방식을 조정해요.

  • PLT_LINKLET_SHOW_GENSYM — 약어 대신 전체 생성된 이름을 출력해요. 기본 동작은 Chez Scheme의 print-gensym에 대한 'pretty/suffix 모드에 해당해요.
  • PLT_LINKLET_SHOW_PRE_JIT — JIT 모드로의 변환 전에 스케미파이드 형식을 보여줘요. PLT_CS_JIT가 설정된 경우에만 적용돼요.
  • PLT_LINKLET_SHOW_LAMBDA — 해석된 바깥 윤곽을 가진 더 큰 형식 안에서 컴파일되는 개별 스케미파이드 형식을 보여줘요.
  • PLT_LINKLET_SHOW_POST_LAMBDA — 내부 개별 형식들이 컴파일된 후의 바깥 형식을 보여줘요.
  • PLT_LINKLET_SHOW_POST_INTERP — 해석 가능한 형식으로 변환된 후의 바깥 형식을 보여줘요.
  • PLT_LINKLET_SHOW_JIT_DEMANDPLT_CS_JIT를 설정한 컴파일로 이전에 준비된 형식들의 JIT 컴파일을 보여줘요.
  • PLT_LINKLET_SHOW_KNOWN — 스케미파이드 형식과 함께 기록된 알려진 바인딩 정보를 보여줘요.
  • PLT_LINKLET_SHOW_CP0 — Chez Scheme의 프론트엔드 최적화기(optimizer)에 의한 변환 후의 스케미파이드 형식을 보여줘요.
  • PLT_LINKLET_SHOW_PASSES — Chez Scheme의 내부 표현에서, 명시된 패스(공백으로 구분해 나열) 이후의 스케미파이드 링클릿 중간 형식을 보여줘요. 특별한 이름 all은 모든 Chez Scheme 패스 이후의 중간 형식을 보여줘요.
  • PLT_LINKLET_SHOW_ASSEMBLY — Chez Scheme의 머신 명령어 추상화로 표현한 스케미파이드 링클릿의 컴파일된 형식을 보여줘요.

시작 시 PLT_LINKLET_TIMES 환경 변수가 설정되면, 종료 시 Racket이 컴파일 시간과 평가 시간에 대한 누적 타이밍 정보를 출력해요. PLT_EXPANDER_TIMES 환경 변수가 설정되면, 종료 시 매크로 확장 시간에 대한 정보가 출력돼요.

package base 버전 8.8.0.10에서 변경됨: PLT_LINKLET_SHOW_PASSES에 특별한 패스 이름 all을 추가했어요. 버전 8.11.1.2에서 변경됨: 출력에 모듈과 링클릿 정보를 추가했어요.

더 알아보기