Tov 벤치마크를 보자마자 저런 결과라면 제대로 설계된 벤치마크일 리 없다고 생각했음. 사용한 자료형만 봐도 분명해 보였는데, 누군가 시간을 들여 실제 비교 수치를 내주니 반가움.
디스패치 벤치마크는 좀 혼란스러움. Tov 코드를 보니 동적 디스패치를 시험하는 것 같은데, Rust 코드를 바꾸면 벤치마크가 측정하는 대상 자체가 달라지는 것 아닌가 싶음.
물론 “Rust보다 빠르다”는 과장임. 특정 작업은 저수준 언어로 더 빠르게 구현할 수 있는 경우가 거의 언제나 있고, 이런 논쟁도 수없이 반복됐음. 다만 이 특정 상황의 동적 디스패치에서는 Tov가 더 빠른 코드를 생성할 가능성이 충분히 있음.
Tov 최적화기가 동적 디스패치를 단형화(monomorphization) 해서 빠른 Rust 버전처럼 동작하게 만드는 것일 수도 있음. 그렇다면 Tov의 장점이지만, 이 예제처럼 동적 디스패치를 쓰는 것은 관용적인 Rust 작성법이 아님. 대부분은 수정된 테스트처럼 열거형을 택할 듯함.
서툰 아마추어 Rust 개발자라고 해도 할 말은 없지만, Rust를 처음 쓸 때부터 std::collections::HashMap 으로 충분해서 ahash는 몰랐음.
이 평가에서 완전히 동의하지 못하는 부분은 거의 이것뿐임. 문서에는 중간 크기 키에서는 성능이 매우 경쟁력 있지만, 정수 같은 작은 키나 긴 문자열 같은 큰 키에서는 다른 해시 알고리즘이 더 빠르며, 그런 알고리즘은 대체로 HashDoS 방어를 제공하지 않는다고 되어 있음. 이걸 읽고 “엄청 느리다”고 받아들이지는 않았음. 그래도 벤치마크를 보면 평가는 괜찮아 보임.
실제 용도 대부분에서는 표준 해시 맵이 충분히 빠름. 하지만 해싱이 실질적인 병목이거나 맵 삽입만 측정하는 벤치마크라면, 금세 언어가 아니라 해시 알고리즘을 비교하는 시험이 됨. 글에서는 Tov/TypeScript가 어떤 해시 알고리즘을 쓰는지, 암호학적 안전성을 의도했는지 밝히지 않았는데, 비교를 완결하려면 이 부분도 다룰 필요가 있음.
정확히는 HashMap 자체가 아니라 기본 해시 함수인 SipHash가 다소 느린 것임. 기억이 맞다면 HashMap은 최첨단 해시 테이블 알고리즘을 쓰는데, SwissTable이었나?
Rust/C/C++의 목표를 오해하는 경우가 많음. 이 언어들은 하드웨어 성능을 최대한 끌어낼 도구를 최대한 많이 제공하고, 필요할 때 꺼내 쓰게 해줌. 그만큼 부가적인 요소가 쌓여 혼란스러워지기도 함.
Tov 같은 언어는 흔한 사용 사례를 최대한 빠르게 만드는 데 집중하지만, 그 범위를 벗어나면 공식적으로 제공되는 최적화 수단이 금세 바닥나고 언어의 제약을 거슬러 작업하게 됨. 솔직히 도구의 한계를 뚫고 최적화하는 건 무척 재미있지만, 업무로 하고 싶지는 않음.