Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize Enum.count/2 #5567

Merged
merged 1 commit into from Dec 16, 2016
Merged

Conversation

michalmuskala
Copy link
Member

@michalmuskala michalmuskala commented Dec 16, 2016

reduce/3 has clauses specialized for various enumerable types, so should be
much faster than the general Enumerable.reduce/3 case, especially that we don't
need additional facilities like terminating the reduction early.

Comparing 3 implementations:

  • map based

    elements |> Enum.map(&(if check(&1), do: 1, else: 0)) |> Enum.sum
    
  • count/2 based

    elements |> Enum.count(&check/1)
    
  • filter based

    elements |> Enum.filter(&check/1) |> Enum.count
    

We get following results before and after the change:

len map count before count after filter
10 2.1706 μs 7.0754 μs 1.6304 μs 1.9765 μs
100 19.921 μs 27.579 μs 13.057 μs 14.591 μs
1000 168.93 μs 178.93 μs 130.76 μs 163.43 μs
10000 2128.9 μs 1822.1 μs 1298.2 μs 1664.6 μs

The most idiomatic code is now also the fastest.

reduce/3 has clauses specialized for various enumerable types, so should be
much faster than the general Enumerable.reduce/3 case, especially that we don't
need additional facilities like terminating the reduction early.

Comparing 3 implementations:

  * map based

        elements |> Enum.map(&(if check(&1), do: 1, else: 0)) |> Enum.sum

  * count/2 based

        elements |> Enum.count(&check/1)

  * filter based

        elements |> Enum.filter(&check/1) |> Enum.count

We get following results before and after the change:

len   | map       | count before | count after | filter
------|-----------|--------------|-------------|------------
10    | 2.1706 μs | 7.0754 μs    | 1.6304 μs   | 1.9765 μs
100   | 19.921 μs | 27.579 μs    | 13.057 μs   | 14.591 μs
1000  | 168.93 μs | 178.93 μs    | 130.76 μs   | 163.43 μs
10000 | 2128.9 μs | 1822.1 μs    | 1298.2 μs   | 1664.6 μs

The most idiomatic code is now also the fastest.
@josevalim josevalim merged commit 9d39ebc into elixir-lang:master Dec 16, 2016
@michalmuskala michalmuskala deleted the enum-count-2 branch January 7, 2018 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants