루비 2.6.0-preview3 릴리스

루비 2.6.0-preview3 릴리스를 알리게 되어 기쁩니다.

루비 2.6.0-preview3은 루비 2.6.0의 세 번째 프리뷰입니다. 이 프리뷰는 다가오는 릴리스 후보에 포함될 기능을 테스트하기 위하여 릴리스되었습니다.

JIT

루비 2.6은 JIT(Just-in-time) 컴파일러의 첫 구현체를 포함합니다.

JIT 컴파일러는 루비 프로그램의 실행 성능을 향상시키는 것이 목적입니다. 다른 언어의 일반적인 JIT 컴파일러와는 다르게, 루비의 JIT 컴파일러는 C 코드를 디스크에 출력한 뒤, 일반적인 C 컴파일러 프로세스를 사용해 네이티브 코드를 생성하도록 합니다. 다음을 참고하세요. Vladimir Makarov가 작성한 MJIT 구조.

JIT 컴파일을 사용하려면 --jit 옵션을 커맨드라인이나 $RUBYOPT 환경 변수에 지정합니다. --jit-verbose=1을 지정하면 실행 중인 JIT 컴파일의 기본적인 정보를 출력합니다. 다른 옵션에 대해서는 ruby --help를 확인하세요.

이번 JIT 릴리스의 주 목적은 2.6 릴리스 전에 각 플랫폼에서 잘 동작하는지, 보안상의 문제가 발생하는지 미리 확인하는 것입니다. 현재 JIT 컴파일러는 루비가 gcc나 clang, Microsoft VC++로 빌드되었으며, 해당 컴파일러가 런타임에서 사용 가능한 경우에만 이용할 수 있습니다. 그 이외에는 아직 이용할 수 없습니다.

2.6.0-preview3에서는 Optcarrot이라는 CPU 성능을 요구하는 벤치마크에서 1.7배의 성능 향상을 이루었습니다(다음을 참조: https://gist.github.com/k0kubun/d7f54d96f8e501bbbc78b927640f4208). Rails 애플리케이션 같은 메모리를 요구하는 작업에서도 성능을 향상시킬 것입니다.

새로운 루비의 성능을 기대해주세요.

RubyVM::AST [Experimental]

루비 2.6에는 RubyVM::AST 모듈이 도입되었습니다.

이 모듈에은 문자열을 파싱하여 AST(추상구문트리)의 노드를 돌려주는 parse 메서드, 파일을 파싱하여 AST의 노드를 돌려주는 parse_file 메서드가 들어있습니다. RubyVM::AST::Node도 도입되었습니다. 이 클래스의 인스턴스로부터 위치정보나 자식 노드를 얻을 수 있습니다. 이 기능은 실험적으로 포함되었으며, AST 노드의 구조는 호환성을 보장하지 않습니다.

새로운 기능

  • Kernel#yield_self의 별칭으로 then이 추가되었습니다. [Feature #14594]

  • rescue가 없는 else가 문법 에러가 됩니다. [EXPERIMENTAL]

  • ASCII 이외의 대문자로 시작하는 상수를 정의할 수 있게 됩니다. [Feature #13770]

  • 종료 지정이 없는 범위 연산자. [Feature #12912]

    종료 지정이 없는 범위 연산자, (1..)가 추가됩니다. 이는 끝이 없는 것처럼 취급됩니다. 다음은 전형적인 사용 예시입니다.

    ary[1..]                          # ary[1..-1]와 동치
    (1..).each {|index| ... }         # 1로 시작하는 무한 루프
    ary.zip(1..) {|elem, index| ... } # ary.each.with_index(1) { ... }
    
  • Binding#source_location을 추가했습니다. [Feature #14230]

    이 메서드는 binding의 소스 코드 상의 위치를 __FILE____LINE__을 가지는 배열로 돌려줍니다. Kernel#evalbinding의 소스 코드의 위치를 무시하도록 변경할 예정입니다. [Bug #4352] 그러므로 지금까지 사용하던 eval("[__FILE__, __LINE__]", binding)로 같은 정보를 획득할 수 없게 됩니다, 앞으로는 Kernel#eval보다는 새로운 Binding#source_location 메서드를 사용하게 될 것입니다.

  • Kernal#system이 실패했을 경우 false를 돌려주는 대신, 에러를 던지도록 하는 :exception 옵션을 추가했습니다. [Feature #14386]

성능 향상

  • Proc#call이 더 이상 $SAFE를 고려하지 않아도 되어 속도가 빨라졌습니다. [Feature #14318]

    Proc#call을 대량으로 호출하는 lc_fizzbuzz 벤치마크가 1.4배 빨라졌습니다. [Bug #10212]

  • block이 블록 파라미터인 경우의 block.call이 빨라졌습니다. [Feature #14330]

    루비 2.5에서는 블록 넘기기의 성능이 향상되었습니다만 [Feature #14045], 추가로 2.6에서는 넘겨진 블록의 호출이 개선되었습니다. 간단한 벤치마크에서 2.6배의 성능 향상을 확인했습니다.

  • Transient Heap(theap)이 도입되었습니다. [Bug #14858] [Feature #14989] theap은 특정 클래스(Array, Hash, Object, Struct)가 가리키는 짧은 생애를 가지는 메모리 객체들을 관리합니다. 예를 들어 작고 짧게 생존하는 Hash 객체는 2배 빨라집니다. rdoc 벤치마크에서 6-7%의 성능 향상을 확인했습니다.

  • Coverage의 oneshot_lines 모드를 추가했습니다. [Feature#15022]

    • 이 모드는 ‘각 줄이 몇 번 실행되었는지’ 대신 ‘각 줄이 한 번 이상 실행되었는지’를 확인합니다. 각 줄의 훅은 최대 1회만 실행되며, 실행된 후에는 플래그를 제거하기 때문에 오버헤드 없이 실행됩니다.
    • Coverage.start:oneshot_lines 키워드 인수가 추가됩니다.
    • Coverage.result:stop:clear 키워드 인수가 추가됩니다. 만약 clear가 참이라면, 이는 카운터를 0으로 초기화합니다. 만약 stop이 참이라면 커버리지 측정을 비활성화합니다.
    • 주어진 소스 코드로부터 ‘stub’을 생성하는 간단한 헬퍼 함수인 Coverage.line_stub을 추가합니다.

2.5 이후 주목할 만한 변경

  • $SAFE가 프로세스 전역 변수로 취급되며, 0 이외의 값을 설정한 후에 0으로 되돌리는 것이 가능해집니다. [Feature #14250]

  • ERB.newsafe_level을 넘기는 기능이 제거될 예정입니다. 또한 trim_modeeoutvar는 키워드 변수로 변경됩니다. [Feature #14256]

  • RubyGems 3.0.0.beta2를 병합했습니다. --ri--rdoc 옵션이 제거되었습니다. 대신에 --document--no-document를 사용해주세요.

  • Bundler를 기본 젬으로 병합했습니다.

자세한 내용은 뉴스커밋 로그를 참고하세요.

이러한 변경사항에 따라, 루비 2.5.0 이후 파일 6474개 수정, 171888줄 추가(+), 46617줄 삭제(-) 하였습니다!

루비 2.6.0-preview3와 함께 즐거운 프로그래밍하세요!

다운로드

  • https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.0-preview3.tar.gz

    SIZE:   17071670 bytes
    SHA1:   67836fda11fa91e0b988a6cc07989fbceda025b4
    SHA256: 60243e3bd9661e37675009ab66ba63beacf5dec748885b9b93916909f965f27a
    SHA512: 877278cd6e9b947f5bb6ed78136efb232dcc9c5c218b7236576171e7c3cd7f6b7d10d07d8402014a14aba1fcd1913a4370f0725c561ead41d8a3fe92029f7f76
    
  • https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.0-preview3.zip

    SIZE:   21537655 bytes
    SHA1:   45f3c90dfffe03b746f21f24152666e361cbb41a
    SHA256: 9152af9e700349dcfa2eec196dd91587d42d70a6837fa2c415ebba1167587be1
    SHA512: 335de36cf56706326f4acc4bbd35be01e0ac5fff30d0a69b2e1630ba4c78f0e711822d1623d0099a517c824b154917d2f60be192dfb143a422cf1d17b38e1183
    
  • https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.0-preview3.tar.bz2

    SIZE:   14973451 bytes
    SHA1:   5f2df5d8c5a3888ccb915d36a3532ba32cda8791
    SHA256: 1f09a2ac1ab26721923cbf4b9302a66d36bb302dc45e72112b41d6fccc5b5931
    SHA512: d1693625723796e8902f3e4c4fae444f2912af9173489f7cf18c99db2a217afc971b082fce7089e39f8edd54d762d2b4e72843c8306ed29b05ccb15ac03dbb5b
    
  • https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.0-preview3.tar.xz

    SIZE:   12291692 bytes
    SHA1:   7f8216247745215e9645568e7a02140f9a029b31
    SHA256: 9856d9e0e32df9e5cdf01928eec363d037f1a76dab2abbf828170647beaf64fe
    SHA512: b4d3b17ecf96272c43cd7518c0b54dee63fc1150ad143e1d9c9d708506fe78676c80eb96cc47b8d46d1128bd483a53f16c944963a03d1f99f00131b74714df7b