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.