Recursion performance: why so slow?

Hello all,

I wanted to implement a simple function that calculates the “hash rate” of my computer. Basically, how many times per second my computer can compute a sha256 hash. So I came up with this simple function:

defmodule HashRate do
  def estimate_hash_rate(interval \\ 20) do
     start = System.system_time(:second)
     n = estimate_hash_rate(interval, start, 0)
     n / (interval * 1000) # result in khs 
  end
  def estimate_hash_rate(interval, start, n \\ 0) do
    if start + interval < System.system_time(:second) do
      n
    else
      :crypto.hash(:sha256, "data#{n}")
      estimate_hash_rate(interval, start, n + 1)
    end
  end
end

It runs during 20 seconds and count how many times it performs the hash. When I run this function multiple times, I get results like 378.59365, 337.1613

I implemented a similar algorithm in Go and got much faster results : 5236.6924, 5468.282. Here is the code:

func main() {
	interval := int32(20)
	start := int32(time.Now().Unix())
	n := 0
	for {
		if start + interval < int32(time.Now().Unix()) {
			break
		}
		h := sha256.New()
		h.Write([]byte("data" + strconv.Itoa(n)))
		n += 1
	}

	fmt.Println(float32(n) / float32(interval * 1000))
}

I know Elixir/Erlang may be slow for computation, so I commented out the sha256 hash of my code (to just count the number of iteration per seconds) and got these kinds of results:

Go: 90172.62 (k iterations / s)
Elixir: 5476.6122 (k iterations / s)

Again the difference is HUGE. I don’t think I’m doing anything wrong in my tests. I’m aware of “tail recursivity” (and I believe the function I wrote is tail recursive). I tried to run the code with MIX_ENV=prod but got same kind of results.

Any ideas of what is going on ? What makes Elixir so slow compared to Go in this naive test ? Maybe System.system_time(:second) ? Or maybe I’m doing something wrong ??