How deep a storage profile fans its keys out (StorageProfile.key_levels, V216).
A file's folder is <prefix>/<md5>, with levels two-character hash folders
between them:
0 lib-1a2b3c/22e8b90781bab72967f9d5410b4299f9/…
1 lib-1a2b3c/22/22e8b90781bab72967f9d5410b4299f9/… (the layout so far)
2 lib-1a2b3c/22/e8/22e8b90781bab72967f9d5410b4299f9/…
3 lib-1a2b3c/22/e8/b9/22e8b90781bab72967f9d5410b4299f9/…Each hash folder has 256 possible names, and MD5 spreads files evenly over
them, so n files leave about n / 256^levels file folders in each folder at
the deepest level. That number is what a local disk feels (listing, backups,
rsync); an object store has no folders and does not care. The layout applies
to new uploads: a file's folder is stored on its row, so nothing already
uploaded moves.
Summary
Functions
The number of files at which levels stops being comfortable.
The layout every profile had before it could be chosen (V216).
The layouts a profile may choose: the number of hash folders.
The folder of a file: prefix, levels hash folders, then the MD5.
About how many file folders the busiest folder holds once a library has files
files, under levels.
How a folder of per_folder entries fares: :comfortable, :slow or :too_many.
The library sizes the Storage profiles tab compares.
One row per library size: {files, per_folder, rating} under levels.
Whether levels is a layout.
Functions
@spec comfortable_up_to(0..3) :: pos_integer()
The number of files at which levels stops being comfortable.
@spec default() :: 1
The layout every profile had before it could be chosen (V216).
@spec levels() :: [0..3]
The layouts a profile may choose: the number of hash folders.
@spec path(String.t(), String.t(), non_neg_integer()) :: String.t()
The folder of a file: prefix, levels hash folders, then the MD5.
iex> PhoenixKit.Modules.Storage.KeyLayout.path("lib-1a2b", "22e8b907", 0)
"lib-1a2b/22e8b907"
iex> PhoenixKit.Modules.Storage.KeyLayout.path("lib-1a2b", "22e8b907", 1)
"lib-1a2b/22/22e8b907"
iex> PhoenixKit.Modules.Storage.KeyLayout.path("lib-1a2b", "22e8b907", 2)
"lib-1a2b/22/e8/22e8b907"
@spec per_folder(non_neg_integer(), 0..3) :: non_neg_integer()
About how many file folders the busiest folder holds once a library has files
files, under levels.
iex> PhoenixKit.Modules.Storage.KeyLayout.per_folder(1_000_000, 1)
3907
iex> PhoenixKit.Modules.Storage.KeyLayout.per_folder(1_000_000, 0)
1000000
@spec rating(non_neg_integer()) :: :comfortable | :slow | :too_many
How a folder of per_folder entries fares: :comfortable, :slow or :too_many.
@spec sizes() :: [pos_integer()]
The library sizes the Storage profiles tab compares.
@spec table(0..3) :: [{pos_integer(), non_neg_integer(), atom()}]
One row per library size: {files, per_folder, rating} under levels.
Whether levels is a layout.