이 글과 https://lobste.rs/s/gajtrm/debunking_faster_than_rust_malicious 가 지금 첫 화면에 같은 추천 수로 나란히 있는 게 재미있음. 둘 다 자동 메모리 관리 언어의 컴파일러가 보통 더 빠르다고 여겨지는 언어와 성능으로 경쟁하는 내용인데, 댓글 분위기는 무척 다름.
일부 입력에서 roc-deflate가 libdeflate보다 빨랐어도 “Roc이 C보다 빠르다”라고 결론 내릴 수 없는 이유를 명시해 두길 잘했다고 느낌. “X가 Rust/C/C++/Zig보다 빠르다”는 말을 들으면 나도 본능적으로 의구심이 듦. 이 언어들은 모두 하드웨어의 기능을 최대한 활용할 수단을 제공하므로, 차이는 사용 편의성과 보장 사항에 있지 성능의 상한에 있지 않음.
다만 Rust, C, C++ 모두 부호 없는 정수의 래핑이 없음을 보장하는 산술 연산은 제공하지 않음.
기회적 변경(opportunistic mutation) 이라는 개념이 꽤 멋짐! 다만 이 코드가 별다른 최적화 없이 자연스럽게 작성한 코드와 얼마나 가까운지, 관용적인 코드라고 볼 수 있는지 궁금함.
성능을 끝까지 쥐어짜려 하지 않고 평소에 작성할 법한 Roc 코드인지를 묻는다면, 성능 최적화의 흔적은 확실히 드러남. 가장 눈에 띄는 것은 일부에서 쓰는 List.prefetched임. 성능 외에는 아무 효과가 없으며, 사용 위치에 따라 오히려 느려질 수도 있으므로 측정 후에만 쓰는 편이 좋음.
반복문 밖에 중복처럼 보이는 명시적 범위 검사를 넣어, 최적화기가 반복문 안의 자동 범위 검사를 안전하게 생략하게 한 것도 마찬가지임. 처음 구현할 때부터 넣기보다는 측정 후에 적용할 기법임. 컬렉션을 새로 만들지 않고 비워서 재사용하는 것도 여기에 해당함.
roc-deflate의 코드는 평범하지는 않지만 과도하게 기괴하지도 않다고 봄. Roc에서는 특이한 기법 없이도 좋은 성능을 낼 수 있어야 하지만, 이번처럼 최대 성능이 목표라면 이해 가능한 범위에서 비일상적인 코드를 작성하는 것은 괜찮다고 봄.
작성자가 제공한 shell script를 제대로 읽었다면, 작업 내역과 분기한 원본 커밋, 반영된 변경 사항은 다음 링크에서 확인 가능함. pull request, ancestor/original, improved, overallcomparison.
Roc은 잘 모르지만, roc-deflate의 더 단순한 이전 구현과 비교해 보고 싶음. 대부분은 여러 언어에 통하는 최적화이고 일부만 Roc 전용이라고 하는데, 변경 내역만으로는 둘을 구별하기 어려움. 단순한 구현에서 얼마나 벗어났는지, 개선 방법이 얼마나 자명한지와 왜 이전에는 적용하지 않았는지, 초기 설계가 나중의 성능 목표와 충돌할 것을 미리 알아챌 단서는 무엇인지 궁금함.
결국 Roc에 능숙하지 않은 개발자도 이런 성능에 얼마나 쉽게 도달할 수 있느냐가 핵심임. 나는 Zig로 실제 사용하는 프로그램을 작성하며 프로젝트가 발전하는 과정에서 최적화를 어떻게 다룰지 고민 중임. 일부 작은 도구는 단순하고 명백한 접근만으로도 기존 Go 도구보다 빨랐고, 읽기 쉬운 Zig 표준 라이브러리를 따라가는 것만으로 충분한 경우도 많았음. 다만 Zig 표준 라이브러리의 가독성은 언어가 아직 젊고 성숙하지 않았기 때문에 나타나는 일시적 특성이라는 주장도 있음. 아직 끌어낼 성능이 많이 남아 있고 그 대가가 가독성 저하라면, 정말 그러지 않기를 바람.
이론적으로 가능한 최고 성능도 흥미롭지만, 실무에서는 내 역량과 자원으로 가능한 성능이 더 유용함. 겉보기에는 동등한 초기 설계 선택이 성능에 큰 차이를 만드는지도 알고 싶음. 잘못된 코드를 작성했거나 잘못 설계된 대규모 코드베이스를 인계받았을 때, 거기서 벗어나는 데 얼마나 많은 작업이 필요한지도 궁금함.
Zig는 고성능 코드를 편하게 작성하는 것이 주요 목표지만, Roc의 초점은 다른 곳에 있음. 이런 성능을 달성할 수 있기를 바라지만, 일반적인 Roc 개발자가 이 정도까지 최적화하거나 그럴 필요가 있으리라고 예상하지는 않음. 대부분의 Go, TypeScript, Python, Java 개발자가 최고 성능의 압축 알고리즘을 구현할 줄 몰라도 되는 것과 같음.
잘못 설계된 대규모 코드베이스를 얼마나 쉽게 개선할 수 있느냐는 내게도 중요한 질문임. 대규모 코드베이스에서도 “Roc-Specific Optimizations”에 나온 기법 중 첫 번째인 불필요한 공유 피하기 외에는 대체로 알 필요가 없으리라고 봄. 초보자가 예상보다 훨씬 느린 코드를 Roc Zulip에 올리면, 숙련자가 불필요하게 공유한 값을 찾아주고 이를 고치자마자 빨라지는 일이 일종의 통과의례처럼 벌어짐.
다행히 이런 코드는 아주 초기부터 증상이 뚜렷해서, 잘못된 토대 위에 계속 개발하다 나중에 재작성해야 하는 경우는 아직 보지 못했음. 다만 규모가 큰 Roc 코드베이스 자체가 아직 적고, 수십만 줄 규모는 들어봤어도 백만 줄 이상은 아직 들어보지 못했음. 지금까지의 양상이 계속 유지될 것으로 낙관함.
Roc이 독자적인 언어로서, 또 Gleam과 함께 함수형 프로그래밍을 이끌어가는 언어로서 무엇을 해낼지 무척 기대됨. Gleam도 꽤 주목받고 있지만, 나는 후원자라 편향이 있을 수 있음.
Richard와 몇 번 대화할 기회가 있었는데, 늘 사려 깊고 유쾌했음.