Skip to content

Instantly share code, notes, and snippets.

@skovmand
Last active August 13, 2019 07:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skovmand/bcea31e8c8990784358dd145f34fd554 to your computer and use it in GitHub Desktop.
Save skovmand/bcea31e8c8990784358dd145f34fd554 to your computer and use it in GitHub Desktop.
Comparison of Stream.filter, Enum.filter and Enum.filter+Enum.any? for filtering a list of tracks
Comparison of Stream.filter, Enum.filter and Enum.filter+Enum.any? for filtering a list of tracks
----------------------------------------------
Using 2680 tracks:
Name ips average deviation median 99th %
Enum.filter 466.59 2.14 ms ±24.75% 2.00 ms 3.13 ms
Stream.filter 440.91 2.27 ms ±24.00% 2.20 ms 3.18 ms
Enum.filter + Enum.any? 407.53 2.45 ms ±26.21% 2.32 ms 3.45 ms
Comparison:
Enum.filter 466.59
Stream.filter 440.91 - 1.06x slower +0.125 ms
Enum.filter + Enum.any? 407.53 - 1.14x slower +0.31 ms
----------------------------------------------
Using 26800 tracks:
Name ips average deviation median 99th %
Enum.filter 44.34 22.55 ms ±3.14% 22.34 ms 24.77 ms
Stream.filter 40.04 24.97 ms ±4.64% 24.91 ms 28.55 ms
Enum.filter + Enum.any? 37.58 26.61 ms ±4.64% 26.52 ms 31.90 ms
Comparison:
Enum.filter 44.34
Stream.filter 40.04 - 1.11x slower +2.42 ms
Enum.filter + Enum.any? 37.58 - 1.18x slower +4.05 ms
----------------------------------------------
Code used:
Benchee.run(
%{"<Name here>" => fn -> FlowerBoy.Tracks.query([FlowerBoy.Filters.tag_filter("running"), FlowerBoy.Filters.query_filter("foo fighters")]) end}
)
Stream.filter:
# Applies filters to a list of tracks
# All supplied filter functions must work with Enum.filter/2
@spec apply_filters(tracks :: [Track.t()], filters :: [Filters.filter()]) :: [Track.t()]
defp apply_filters(tracks, filters) do
filters
|> Enum.reduce(tracks, fn filter, acc -> Stream.filter(acc, filter) end)
end
Enum.filter:
defp apply_filters(tracks, filters) do
filters
|> Enum.reduce(tracks, fn filter, acc -> Enum.filter(acc, filter) end)
end
Enum.filter + Enum.any?
defp apply_filters(tracks, filters) do
tracks
|> Enum.filter(fn track -> !Enum.any?(filters, fn filter -> filter.(track) == false end) end)
end
@skovmand
Copy link
Author

Of course, if there are several filter functions, that each only exclude a few tracks, Stream.Filter will probably be faster than Enum.filter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment