Skip to content
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

Alternative base62 encoder #3

Open
pma opened this issue Nov 16, 2018 · 0 comments
Open

Alternative base62 encoder #3

pma opened this issue Nov 16, 2018 · 0 comments

Comments

@pma
Copy link

pma commented Nov 16, 2018

Hi,

I've been playing with your code and implemented an alternative generator that seems to be a bit faster (6.6 s vs 12.5 s for 1M). The speed-up comes from the base62 encoding. I'm using compiled functions for the base62 encoder and accumulate digits as a list with an iodata_to_binary at the end, instead of binary concatenation. Sharing this in case you want to use any of the ideas in your implementation.

defmodule Ksuid do
  import System, only: [system_time: 1]
  import :crypto, only: [strong_rand_bytes: 1]
  import IO, only: [iodata_to_binary: 1]

  @epoch 1_400_000_000

  def new() do
    encode(<<(system_time(:second) - @epoch)::integer-size(32), strong_rand_bytes(16)::binary-16>>)
  end

  for {encoding, value} <- Enum.with_index('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz') do
    defp enc(unquote(value)), do: <<unquote(encoding)>>
  end

  defp encode(binary) do
    <<n::size(160)>> = binary
    encode(n, [])
  end

  defp encode(n, r) do
    d = rem(n, 62)
    i = div(n, 62)
    r = [enc(d) | r]

    if i === 0, do: iodata_to_binary(r), else: encode(i, r)
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant