SaturnPlayer.get(name, uuid) (common/src/main/java/org/saturnclient/client/player/SaturnPlayer.java) can't tell "not fetched yet" apart from "fetched, not a Saturn user". Both are stored as null:
SaturnPlayerplayer=PLAYERS.get(uuid);if(player==null){PLAYERS.put(uuid,null);QUEUE.add(uuid);// re-queued on every callstartPlayerThread();}
When get_player returns null (the player isn't running Saturn), the worker stores null. The next call re-queues the player, and so on forever.
It's called from the render path in every versions/* folder:
PlayerEntityRendererMixin: every visible player, every frame
TabListMixin: every tab-list entry, whenever the tab list renders
With 20 non-Saturn players visible at 60 FPS, that's about 1,200 queue entries per second. The worker sends one blocking get_player per entry to the production server, so:
the ConcurrentLinkedQueue grows without bound (client memory)
the server receives a constant stream of get_player requests
real Saturn players' cosmetics load late, stuck behind the backlog
Fix
Record lookups that returned null, for example with containsKey or a "not Saturn" marker, and don't re-queue them.
Re-check them only after a cooldown (say 60 s), or when the server announces the player through the player notification.
Don't queue a UUID that is already queued or in flight.
## Problem
`SaturnPlayer.get(name, uuid)` (`common/src/main/java/org/saturnclient/client/player/SaturnPlayer.java`) can't tell "not fetched yet" apart from "fetched, not a Saturn user". Both are stored as `null`:
```java
SaturnPlayer player = PLAYERS.get(uuid);
if (player == null) {
PLAYERS.put(uuid, null);
QUEUE.add(uuid); // re-queued on every call
startPlayerThread();
}
```
When `get_player` returns `null` (the player isn't running Saturn), the worker stores `null`. The next call re-queues the player, and so on forever.
It's called from the render path in every `versions/*` folder:
- `PlayerEntityRendererMixin`: every visible player, every frame
- `TabListMixin`: every tab-list entry, whenever the tab list renders
With 20 non-Saturn players visible at 60 FPS, that's about 1,200 queue entries per second. The worker sends one blocking `get_player` per entry to the production server, so:
- the `ConcurrentLinkedQueue` grows without bound (client memory)
- the server receives a constant stream of `get_player` requests
- real Saturn players' cosmetics load late, stuck behind the backlog
## Fix
- Record lookups that returned `null`, for example with `containsKey` or a "not Saturn" marker, and don't re-queue them.
- Re-check them only after a cooldown (say 60 s), or when the server announces the player through the `player` notification.
- Don't queue a UUID that is already queued or in flight.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
SaturnPlayer.get(name, uuid)(common/src/main/java/org/saturnclient/client/player/SaturnPlayer.java) can't tell "not fetched yet" apart from "fetched, not a Saturn user". Both are stored asnull:When
get_playerreturnsnull(the player isn't running Saturn), the worker storesnull. The next call re-queues the player, and so on forever.It's called from the render path in every
versions/*folder:PlayerEntityRendererMixin: every visible player, every frameTabListMixin: every tab-list entry, whenever the tab list rendersWith 20 non-Saturn players visible at 60 FPS, that's about 1,200 queue entries per second. The worker sends one blocking
get_playerper entry to the production server, so:ConcurrentLinkedQueuegrows without bound (client memory)get_playerrequestsFix
null, for example withcontainsKeyor a "not Saturn" marker, and don't re-queue them.playernotification.