CxLeaderboard - a comprehensive leaderboard library

Are you inserting values dynamically? The entire leaderboard is recalculated on each insert, it’s meant for rare writes and frequent reads.

yeah, we update the leaderboard in the core game loop when
player’s elo change after each match and it is about a minute each. here is the update code

  def update(uid, elo, name, country \\ :global) do
    spawn(fn ->
      country = if (country == :"0") do :global else country end
      if (country != :global) do
        Leaderboard.add_or_update(Leaderboard.client_for(:global), {{-round(elo), uid}, {name, country} })
      end
      Leaderboard.add_or_update(Leaderboard.client_for(country), {{-round(elo), uid}, {name, country} })
    end)
  end

had to add spawn hack fix to make respone faster

Try removing all instances of client_for and replace them with another function like

  def get_lb(name) do
    %CxLeaderboard.Leaderboard{
      state: name,
      indexer: nil,
      store: CxLeaderboard.EtsStore
    }
  end

I had to do that in my code because I realized client_for is a blocking call into a genserver.

That said, a lot of inserts are definitely going to slow things down because each time it has to re-read everything from db to re-build the leaderboard.

since cx isn’t for my use case is it worth the effort to swap in https://github.com/jur0/leaderboard I don’t know enough about fp / elixir to judge if its better for writes

Don’t see how that would really help, it’s also built on ets + genserver. Fast inserts with proper ranking is a complex use-case that requires a much more sophisticated tree-based algorithm. And your rebuilds are probably database-bound. The best recommendation I could give is to replace ranked leaderboard with just a list sorted by score, assuming you are storing the score in your database.

If ranking is necessary and you’re using postgres, maybe look into achieving the same result with its RANK() function.

And of course make sure your db tables have the correct indexes on them for whatever you’re doing. I had 200k leaderboard rebuilt in 11 seconds.

The score is in both in PostgreSQL and Redis, I tried looking for a leaderboard in elixir + Redis but can’t find any.

for now I will add in your suggested fix.

Actually, only use my fix in places where you read from leaderboard, keep using client_for where you write/update something.

1 Like