2P by GN⁺ 4달전 | ★ favorite | 댓글 1개

Ruby의 성능 향상: C를 Ruby로 다시 작성하기

Ruby의 성능 비교
  • 최근 언어 비교 리포지토리에서 Ruby는 R과 Python보다 빠르지만, 세 번째로 느린 언어로 평가됨.
  • 벤치마크는 "Loops"와 "Fibonacci" 두 가지로 구성되며, 각각 루프와 조건문, 함수 호출 오버헤드 및 재귀 성능을 강조함.
Ruby와 Node.js의 성능 비교
  • M3 MacBook Pro에서 Ruby 3.3.6은 루프 예제에서 28초, 피보나치 예제에서 12초 소요됨.
  • Node.js는 두 예제 모두 1초 정도 소요됨.
  • M2 MacBook Air에서는 Ruby의 성능이 더 나빠짐.
벤치마크의 의미
  • 이러한 벤치마크는 실제로 큰 의미가 없을 수 있음.
  • Python은 가장 느린 언어로 평가되었지만, GitHub에서 가장 많이 사용되는 언어임.
  • 프로그래밍 언어는 효율적이어야 하며, 언어의 유용성과 생산성이 성능보다 중요함.
YJIT의 적용
  • YJIT를 적용하면 피보나치 성능이 크게 향상됨.
  • 루프 예제에서는 성능 향상이 미미함.
Ruby 코드 최적화
  • Range#each는 C로 작성되어 YJIT 최적화가 불가능함.
  • Integer#times는 Ruby 3.3에서 C에서 Ruby로 변환되어 YJIT 최적화가 가능함.
  • Array#each는 Ruby 3.4에서 C에서 Ruby로 변환됨.
Integer#times 최적화
  • Integer#succi += 1보다 빠르게 동작함.
  • YJIT는 Integer#times를 최적화하여 성능을 크게 향상시킴.
Array#each 최적화
  • Array#each는 Ruby 3.4에서 C에서 Ruby로 변환되어 YJIT 최적화가 가능함.
  • Primitive 모듈을 사용하여 C 코드를 Ruby에서 평가함.
Ruby Microbench 리포지토리
  • 다양한 Ruby 버전과 YJIT를 사용하여 벤치마크를 실행함.
  • Ruby 3.4 YJIT는 성능이 크게 향상됨.
range#each 최적화
  • Range 클래스를 순수 Ruby로 구현하여 성능을 향상시킬 수 있음.
YJIT 표준 라이브러리
  • YJIT 팀은 C 코드를 Ruby로 대체하여 성능을 향상시키고 있음.
  • with_yjit 블록을 사용하여 YJIT가 활성화되었을 때 Ruby 구현을 사용함.
YJIT 최적화 조사
  • YJIT는 Ruby VM 바이트코드를 기계어로 변환하여 성능을 최적화함.
  • Integer#succ의 기계어 코드를 분석하여 YJIT의 최적화 과정을 이해함.
Hacker News 의견
  • 루프 예제는 10억 번 반복하며 중첩 루프를 사용함. 이 벤치마크는 첫 두 줄에서 99% 이상의 시간을 소비할 것이라고 추측됨

    • 배열 요소에 대한 활력 분석을 통해 전체 외부 루프를 제거할 수 있으며, 프로그램을 간단하게 변환할 수 있음
    • 컴파일러가 이러한 분석을 수행할 수 있는지 궁금함
    • u가 컴파일 시점에 알려지지 않더라도 내부 루프는 몇 가지 명령어로 대체 가능함
  • Ruby의 향후 버전에 대한 언급이 있으며, Ruby 3.4.0은 이번 크리스마스에, Ruby 3.5.0은 다음 크리스마스에 출시될 예정임

    • Python의 최소 JIT가 이러한 루프에 어떤 영향을 미칠지 궁금함
    • Python 3.13은 JIT가 활성화된 상태로 빌드되어야 하며, 이를 통해 벤치마크를 실행해보는 것이 흥미로울 것임
  • Ruby에 대한 애정이 여전히 남아있음. Matz에게 감사함

  • Integer#succ의 성능 개선 PR이 2024년 초에 있었으며, 이를 통해 Integer#succ를 사용하는 이유를 이해하게 됨

    • Integer#succ는 루프 메서드를 재작성할 때 사용되며, 해석기에서 opt_succ (i = i.succ)putobject 1; opt_plus (i += 1)보다 더 빠르게 처리됨
    • 개인적으로 #succ를 가독성 때문에 자주 사용하며, UUID 라이브러리의 #bytes 메서드에서 두 번 사용하여 코드 읽기 시 "비트 슬라이싱 모드"를 유지함
  • TruffleRuby와 관련된 경험을 공유하며, TruffleRuby가 Node.js보다 빠르고 Bun이나 Golang에 근접함

    • 제공된 벤치마크가 변경 후의 TruffleRuby 속도를 보여주는지 확신할 수 없음
    • 벤치마크를 검증하고 메인 저장소에 커밋으로 추가하고 싶음
  • Ruby가 매우 빨라졌으며, TruffleRuby는 더욱 인상적임

  • YJIT가 Rust로 작성되었다는 사실을 몰랐음

  • Python이 벤치마크에서 가장 느린 언어였지만, 2024년 10월 기준으로 Github에서 가장 많이 사용되는 언어임

    • 언어의 느림과 인기가 상관관계가 있는 것 같음
  • 더 많은 언어를 포함한 오래된 언어 비교 저장소가 있음

  • Advent of Code 솔루션에 큰 변화를 가져왔으며, 놀랍도록 유사하게 보임