Created
February 6, 2019 19:15
-
-
Save potatosalad/15fcc122b1b5f5c8fd5146f6faf1dd5c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
n = 1_000_000 | |
bmap = FooBench.start(FooMap, n) | |
btup = FooBench.start(FooTuple, n) | |
Benchee.run(%{ | |
"bmap.read" => fn -> FooBench.readall(bmap) end, | |
"btup.read" => fn -> FooBench.readall(btup) end | |
}, memory_time: 5) | |
Benchee.run(%{ | |
"bmap.clean" => fn -> FooBench.clean(bmap); FooBench.write(bmap) end, | |
"btup.clean" => fn -> FooBench.clean(btup); FooBench.write(btup) end | |
}, memory_time: 5) | |
:ok = FooBench.stop(bmap) | |
:ok = FooBench.stop(btup) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule FooBench do | |
defstruct module: nil, store: [] | |
def start(module, number) do | |
store = module.store_start(number) | |
%__MODULE__{module: module, store: store} | |
end | |
def stop(%__MODULE__{module: module}) do | |
module.stop() | |
end | |
def clean(%__MODULE__{module: module, store: store}) do | |
module.store_clean(store) | |
end | |
def write(%__MODULE__{module: module, store: store}) do | |
module.store_write(store) | |
end | |
def readall(%__MODULE__{module: module, store: store}) do | |
module.store_readall(store) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule FooMap do | |
@stale_after 30_000 | |
@ets :foo_map | |
defmodule Data do | |
defstruct core_object: nil, stored_at: nil | |
end | |
def start() do | |
@ets = :ets.new(@ets, [:set, :public, :named_table, {:read_concurrency, true}]) | |
:ok | |
end | |
def stop() do | |
true = :ets.delete(@ets) | |
:ok | |
end | |
def get(core_id) do | |
stale_time = :erlang.monotonic_time(:millisecond) - @stale_after | |
case :ets.lookup(@ets, core_id) do | |
[{^core_id, %Data{core_object: cached_object, stored_at: stored_at}}] when stored_at > stale_time -> | |
cached_object | |
[_] -> | |
:stale | |
[] -> | |
nil | |
end | |
end | |
def put(core_id, cached_object) do | |
true = :ets.insert(@ets, {core_id, %Data{core_object: cached_object, stored_at: :erlang.monotonic_time(:millisecond) + @stale_after}}) | |
:ok | |
end | |
def clean(current_monotonic_time \\ :erlang.monotonic_time(:millisecond)) do | |
# match_spec = [{{:_, :"$1", :_}, [{:"=<", :"$1", current_monotonic_time}], [true]}, {:_, [], [false]}] | |
match_spec = [{{:_, %{__struct__: FooMap.Data, stored_at: :"$1"}}, [{:"=<", :"$1", current_monotonic_time}], [true]}, {:_, [], [false]}] | |
count = :ets.select_delete(@ets, match_spec) | |
count | |
end | |
def store_start(number) do | |
stored_at = :erlang.monotonic_time(:millisecond) + 30_000 | |
store = | |
for i <- 1..number, into: [] do | |
key = "#{i}" | |
value = %{id: key, name: :binary.copy("1234", 16)} | |
{key, %Data{core_object: value, stored_at: stored_at}} | |
end | |
:ok = start() | |
:ok = store_write(store) | |
store | |
end | |
def store_clean(store) do | |
expected_length = length(store) | |
current_time = :erlang.monotonic_time(:millisecond) + 30_000 | |
^expected_length = clean(current_time) | |
end | |
def store_write(store) do | |
true = :ets.insert(@ets, store) | |
:ok | |
end | |
def store_readall(store) do | |
do_store_readall(store) | |
end | |
defp do_store_readall([{key, %{core_object: value}} | rest]) do | |
^value = __MODULE__.get(key) | |
do_store_readall(rest) | |
end | |
defp do_store_readall([]) do | |
:ok | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule FooTuple do | |
@stale_after 30_000 | |
@ets :foo_tuple | |
defmodule Data do | |
defstruct core_object: nil, stored_at: nil | |
end | |
def start() do | |
@ets = :ets.new(@ets, [:set, :public, :named_table, {:read_concurrency, true}]) | |
:ok | |
end | |
def stop() do | |
true = :ets.delete(@ets) | |
:ok | |
end | |
def get(core_id) do | |
stale_time = :erlang.monotonic_time(:millisecond) - @stale_after | |
case :ets.lookup(@ets, core_id) do | |
[{^core_id, stored_at, cached_object}] when stored_at > stale_time -> | |
cached_object | |
[_] -> | |
:stale | |
[] -> | |
nil | |
end | |
end | |
def put(core_id, cached_object) do | |
true = :ets.insert(@ets, {core_id, :erlang.monotonic_time(:millisecond) + @stale_after, cached_object}) | |
:ok | |
end | |
def clean(current_monotonic_time \\ :erlang.monotonic_time(:millisecond)) do | |
match_spec = [{{:_, :"$1", :_}, [{:"=<", :"$1", current_monotonic_time}], [true]}, {:_, [], [false]}] | |
count = :ets.select_delete(@ets, match_spec) | |
count | |
end | |
def store_start(number) do | |
stored_at = :erlang.monotonic_time(:millisecond) + 30_000 | |
store = | |
for i <- 1..number, into: [] do | |
key = "#{i}" | |
value = %{id: key, name: :binary.copy("1234", 16)} | |
{key, stored_at, value} | |
end | |
:ok = start() | |
:ok = store_write(store) | |
store | |
end | |
def store_clean(store) do | |
expected_length = length(store) | |
current_time = :erlang.monotonic_time(:millisecond) + 30_000 | |
^expected_length = clean(current_time) | |
end | |
def store_write(store) do | |
true = :ets.insert(@ets, store) | |
:ok | |
end | |
def store_readall(store) do | |
do_store_readall(store) | |
end | |
defp do_store_readall([{key, _, value} | rest]) do | |
^value = __MODULE__.get(key) | |
do_store_readall(rest) | |
end | |
defp do_store_readall([]) do | |
:ok | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Name ips average deviation median 99th % | |
btup.read 0.55 1.83 s ±10.86% 1.87 s 2.01 s | |
bmap.read 0.48 2.09 s ±12.01% 2.05 s 2.36 s | |
btup.clean 0.85 1.18 s ±1.19% 1.18 s 1.20 s | |
bmap.clean 0.82 1.21 s ±1.59% 1.21 s 1.24 s | |
Comparison: | |
btup.read 0.55 | |
bmap.read 0.48 - 1.14x slower | |
btup.clean 0.85 | |
bmap.clean 0.82 - 1.03x slower | |
Memory usage statistics: | |
Name Memory usage | |
btup.read 526.43 MB | |
bmap.read 633.24 MB - 1.20x memory usage | |
btup.clean 251.81 MB | |
bmap.clean 289.96 MB - 1.15x memory usage |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment