-
Notifications
You must be signed in to change notification settings - Fork 41
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
Compare membership #13
base: master
Are you sure you want to change the base?
Changes from all commits
3eab05b
b755032
c854866
44a5b32
4e29582
7b06914
917386a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
erlang 21.2.6 | ||
elixir 1.8.1-otp-21 | ||
erlang 22.0.1 | ||
elixir 1.8.2-otp-22 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
defmodule Membership.NewMapSetMember do | ||
def check_membership(range, list, _mapset) do | ||
find = Enum.random(range) | ||
mapset = MapSet.new(list) | ||
MapSet.member?(mapset, find) | ||
end | ||
end | ||
|
||
defmodule Membership.MapSetMember do | ||
def check_membership(range, _list, mapset) do | ||
find = Enum.random(range) | ||
MapSet.member?(mapset, find) | ||
end | ||
end | ||
|
||
defmodule Membership.EnumMember do | ||
def check_membership(range, list, _mapset) do | ||
find = Enum.random(range) | ||
Enum.member?(list, find) | ||
end | ||
end | ||
|
||
defmodule Membership.EnumAny do | ||
def check_membership(range, list, _mapset) do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure this is fair to include in this comparison since |
||
find = Enum.random(range) | ||
Enum.any?(list, &(&1 == find)) | ||
end | ||
end | ||
|
||
defmodule Membership.In do | ||
def check_membership(range, list, _mapset) do | ||
find = Enum.random(range) | ||
find in list | ||
end | ||
end | ||
|
||
defmodule Membership.Benchmark do | ||
@inputs %{ | ||
"Large" => {1..1_000_000, Enum.shuffle(1..1_000_000), MapSet.new(1..1_000_000)}, | ||
"Medium" => {1..10_000, Enum.shuffle(1..10_000), MapSet.new(1..10_000)}, | ||
"Small" => {1..100, Enum.shuffle(1..100), MapSet.new(1..100)} | ||
} | ||
|
||
def benchmark do | ||
Benchee.run( | ||
%{ | ||
"New MapSet + MapSet.member?" => fn input -> bench(Membership.NewMapSetMember, input) end, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wasn't sure whether to keep this scenario. It ends up being the slowest for all inputs. Including may be useful to show that you lose all performance benefits when creating a new mapset that's infrequently used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm very in favor of keeping this. Sometimes when folks look at stuff like this they think "oh, MapSet is faster, so I'll use that!" but in the end the added runtime of the conversion ends up making their code slower overall. That's the unfortunate consequence of microbenchmarks. They can be helpful, but you also need to look at the macro picture. |
||
"MapSet.member?" => fn input -> bench(Membership.MapSetMember, input) end, | ||
"Enum.member?" => fn input -> bench(Membership.EnumMember, input) end, | ||
"Enum.any?" => fn input -> bench(Membership.EnumAny, input) end, | ||
"x in y" => fn input -> bench(Membership.In, input) end | ||
}, | ||
time: 10, | ||
inputs: @inputs, | ||
print: [fast_warning: false] | ||
) | ||
end | ||
|
||
defp bench(module, {range, list, mapset}) do | ||
module.check_membership(range, list, mapset) | ||
end | ||
end | ||
|
||
Membership.Benchmark.benchmark() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
%{ | ||
"benchee": {:hex, :benchee, "0.14.0", "f771f587c48b4824b497e2a3e374f75e93ef01fc329873b089a3f5dd961b80b8", [:mix], [{:deep_merge, "~> 0.1", [hex: :deep_merge, repo: "hexpm", optional: false]}], "hexpm"}, | ||
"deep_merge": {:hex, :deep_merge, "0.2.0", "c1050fa2edf4848b9f556fba1b75afc66608a4219659e3311d9c9427b5b680b3", [:mix], [], "hexpm"}, | ||
"benchee": {:hex, :benchee, "1.0.1", "66b211f9bfd84bd97e6d1beaddf8fc2312aaabe192f776e8931cb0c16f53a521", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}], "hexpm"}, | ||
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm"}, | ||
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fairly certain that the runtime of
Enum.random/1
should be constant, but for the sake of making these comparisons even stronger, how would you feel about moving this call to abefore_each
hook so the runtime ofEnum.find/1
isn't included in the comparison?