Skip to content

Commit

Permalink
Add more options for better control
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanwinchester committed Apr 19, 2024
1 parent b84782f commit ef38d27
Show file tree
Hide file tree
Showing 12 changed files with 481 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
inputs: ["{mix,.formatter}.exs", "{bench,config,lib,test}/**/*.{ex,exs}"]
]
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The package can be installed by adding `uuid_v7` to your list of dependencies in
```elixir
def deps do
[
{:uuid_v7, "~> 0.4.2"}
{:uuid_v7, "~> 0.4.3"}
]
end
```
Expand Down Expand Up @@ -66,4 +66,3 @@ defmodule MyApp.Blog.Post do
end
end
```

53 changes: 53 additions & 0 deletions bench/clock_bench.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
defmodule ClockServer do
use GenServer

@clock_size 2 ** 18

def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end

def next do
GenServer.call(__MODULE__, :next)
end

def init(_args) do
state = %{timestamp: System.system_time(:millisecond), counter: clock_init()}
{:ok, state}
end

def handle_call(:next, _from, state) do
current_ts = System.system_time(:millisecond)
# Time-leap protection.
current_ts = if current_ts < state.timestamp, do: state.timestamp, else: current_ts

# Rollover protection.
{current_ts, counter} =
if state.counter == @clock_size do
{current_ts + 1, clock_init()}
else
{current_ts, state.counter + 1}
end

state = %{state | counter: counter, timestamp: current_ts}
{:reply, {current_ts, <<0::1, counter::big-unsigned-17>>}, state}
end

defp clock_init do
<<clock::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
clock
end
end

alias UUIDv7.Clock

{:ok, _pid} = Clock.start_link([])
{:ok, _pid} = ClockServer.start_link([])

Benchee.run(%{
"ClockServer" => fn -> ClockServer.next() end,
"Clock" => fn ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end
})
119 changes: 119 additions & 0 deletions bench/ets_opts.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
set = [
table: [
:named_table,
:public,
:set
]
]

set_read = [
table: [
:named_table,
:public,
:set,
{:read_concurrency, true}
]
]

set_write = [
table: [
:named_table,
:public,
:set,
{:write_concurrency, true}
]
]

set_read_write = [
table: [
:named_table,
:public,
:set,
{:read_concurrency, true},
{:write_concurrency, true}
]
]

ordered_set = [
table: [
:named_table,
:public,
:ordered_set
]
]

ordered_set_read = [
table: [
:named_table,
:public,
:ordered_set,
{:read_concurrency, true}
]
]

ordered_set_write = [
table: [
:named_table,
:public,
:ordered_set,
{:write_concurrency, true}
]
]

ordered_set_read_write = [
table: [
:named_table,
:public,
:ordered_set,
{:read_concurrency, true},
{:write_concurrency, true}
]
]

alias UUIDv7.Clock

Benchee.run(
%{
"set" =>
{fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end, before_scenario: fn _ -> Clock.start_link(set) end},
"set_read" =>
{fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end, before_scenario: fn _ -> Clock.start_link(set_read) end},
"set_write" =>
{fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end, before_scenario: fn _ -> Clock.start_link(set_write) end},
"set_read_write" =>
{fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end, before_scenario: fn _ -> Clock.start_link(set_read_write) end},
"ordered_set" =>
{fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end, before_scenario: fn _ -> Clock.start_link(ordered_set) end},
"ordered_set_read" =>
{fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end, before_scenario: fn _ -> Clock.start_link(ordered_set_read) end},
"ordered_set_write" =>
{fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end, before_scenario: fn _ -> Clock.start_link(ordered_set_write) end},
"ordered_set_read_write" =>
{fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end, before_scenario: fn _ -> Clock.start_link(ordered_set_read_write) end}
},
after_scenario: fn _ -> GenServer.stop(Clock) end
)
143 changes: 143 additions & 0 deletions bench/ets_opts_async_stream.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
set = [
table: [
:named_table,
:public,
:set
]
]

set_read = [
table: [
:named_table,
:public,
:set,
{:read_concurrency, true}
]
]

set_write = [
table: [
:named_table,
:public,
:set,
{:write_concurrency, true}
]
]

set_read_write = [
table: [
:named_table,
:public,
:set,
{:read_concurrency, true},
{:write_concurrency, true}
]
]

ordered_set = [
table: [
:named_table,
:public,
:ordered_set
]
]

ordered_set_read = [
table: [
:named_table,
:public,
:ordered_set,
{:read_concurrency, true}
]
]

ordered_set_write = [
table: [
:named_table,
:public,
:ordered_set,
{:write_concurrency, true}
]
]

ordered_set_read_write = [
table: [
:named_table,
:public,
:ordered_set,
{:read_concurrency, true},
{:write_concurrency, true}
]
]

alias UUIDv7.Clock

Benchee.run(
%{
"set" =>
{fn _ ->
Task.async_stream(1..1_000_000, fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end)
|> Stream.run()
end, before_scenario: fn _ -> Clock.start_link(set) end},
"set_read" =>
{fn _ ->
Task.async_stream(1..1_000_000, fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end)
|> Stream.run()
end, before_scenario: fn _ -> Clock.start_link(set_read) end},
"set_write" =>
{fn _ ->
Task.async_stream(1..1_000_000, fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end)
|> Stream.run()
end, before_scenario: fn _ -> Clock.start_link(set_write) end},
"set_read_write" =>
{fn _ ->
Task.async_stream(1..1_000_000, fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end)
|> Stream.run()
end, before_scenario: fn _ -> Clock.start_link(set_read_write) end},
"ordered_set" =>
{fn _ ->
Task.async_stream(1..1_000_000, fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end)
|> Stream.run()
end, before_scenario: fn _ -> Clock.start_link(ordered_set) end},
"ordered_set_read" =>
{fn _ ->
Task.async_stream(1..1_000_000, fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end)
|> Stream.run()
end, before_scenario: fn _ -> Clock.start_link(ordered_set_read) end},
"ordered_set_write" =>
{fn _ ->
Task.async_stream(1..1_000_000, fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end)
|> Stream.run()
end, before_scenario: fn _ -> Clock.start_link(ordered_set_write) end},
"ordered_set_read_write" =>
{fn _ ->
Task.async_stream(1..1_000_000, fn _ ->
<<seed::big-unsigned-17, _::7>> = :crypto.strong_rand_bytes(3)
Clock.next(<<seed::big-unsigned-17>>)
end)
|> Stream.run()
end, before_scenario: fn _ -> Clock.start_link(ordered_set_read_write) end}
},
after_scenario: fn _ -> GenServer.stop(Clock) end
)
Loading

0 comments on commit ef38d27

Please sign in to comment.