Elixir Livebook으로 Benchee 이용해 간단한 성능측정

posted by donghyun

2 min read

태그

Elixir Livebook으로 간단하게 벤치마크 테스트하기

요즘 AoC를 푸는 등에 Elixir Livebook을 자주 쓰고 있는데, elixir benchmark용 라이브러리인 benchee를 돌리는 데에도 유용하지 않을까 싶어서 한번 써보았다.

예전에 benchee를 mix task처럼 만들어서 mix test 할때마다 돌리도록 하는 방식을 생각해보고 좀 시도해본 적이 있는데, 아무래도 그렇게 쓰기에는 좀 번거롭게 세팅할 부분들이 많고, DB 관련 테스트를 하기에는 테스트 시에 sandbox 모드로 테스트를 하니 실제 환경과는 달라서 크게 유의미한 테스트를 작성하기는 힘들어서 몇번 해보다가 말았었다.

데이터베이스가 연관되지 않은 간단한 성능 테스트를 해보고 싶을때가 몇번 있었는데, 그때마다 mix new 로 새 프로젝트를 만드는건 너무 번거롭고, 그렇다고 elixir script를 만들자니 elixir 1.12 버전 이전에는 Mix.install 같은것도 없었고 등등의 이유로 그냥 넘어갔었다.

그런데 Elixir Livebook을 쓰면 이 안에서 벤치마킹을 아주 간단하게 돌릴 수 있다. 시험 삼아 예전에 관심있었던 Elixir의 Map 자료구조 관련 테스트를 몇가지 해보았다.

Elixir Map의 사이즈에 따른 자료구조 변화 테스트

Elixir(Erlang)의 map의 자료구조는 처음 봤을 때 신기한 자료구조를 하고 있었다. 불변형 데이터를 가진 함수형 언어로써 Key-Value 자료구조를 Hash Map처럼 빠르면서도 메모리 효율적으로 처리할 필요가 있어서 적용된 구조인데, 바로 알고리즘 문제풀이에서 가끔 봤던 Trie 자료구조였다. 정확히는 Trie의 구현체 중 하나인 HAMT(Hash Array Mapped Trie)인데, Ideal Hash Trees에서 제시된 자료구조이다.

Elixir(Erlang)에서는 여기서 더 최적화 tweak을 써서 map이 32개보다 많은 키를 가진 경우에만 HAMT 자료형을 사용한다. 그래서 생기는 흥미로운 현상이 있는데, 특정한 경우에 작은 사이즈의 맵보다 큰 사이즈의 맵이 더 나은 성능을 보여주는 것이다.

Elixir Forum에 이 스레드 에서 이미 테스트를 해본 사람이 있어 그 내용을 가져와서 livebook으로 직접 테스트를 돌려보았다.

실행 스크립트 및 결과

LiveBook 실행 연결 링크

Run in Livebook

결과

실제로 결과를 보면 binary key의 경우 작은 사이즈의 맵보다 큰 사이즈의 맵에서 성능이 더 좋게 나온다. integer와 atom key의 경우에는 작은 사이즈의 맵이 더 나은 성능을 보여주거나 크게 유의미한 차이가 없는것처럼 보이기도 하다.

다음에 해볼 테스트: Elixir Map의 value 조회에 관한 테스트

Map에서 값을 조회하는 방법에는 3가지가 있다.

  1. Map.get/2 사용
  2. Map.fetch/2 사용
  3. Pattern Matching 사용

각각의 성능을 측정해보고자 한다.

결과

실행 스크립트 및 결과

솔직히 기대한 결과가 나오지 않아서 좀 놀랐다. 작은 size의 map의 경우 Pattern Matching방식이 오히려 느렸고, 큰 사이즈의 맵에서는 더 빠르긴 했지만 그 차이가 그렇게 크지 않았다. 무언가 변수 설정을 잘못한 걸지도 모르겠다.

참고

Elixir로 어떤 기능들에 대해 구현 방법에 따른 성능 차이를 보여주는 benchmark들을 올려놓은 레포가 있어 참고로 보면 좋을것 같다.

https://github.com/devonestes/fast-elixir