Fix state locking for getTopMRUProfiles & getProfileIfCached

Also add missing last access update in getProfileIfCached
This commit is contained in:
Jason Penilla 2022-03-17 19:44:45 -07:00 committed by Jason
parent 2eeca6f108
commit 319d5fa29f
3 changed files with 50 additions and 15 deletions

View File

@ -599,17 +599,21 @@ index b49528d8a2c577def4f74ee694ffd53b481acb32..8f5784ed4df46f3c7d4c6b4ff76ad839
GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository();
GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName()));
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
index c3e3a9950ee05dc97f15ab128e40854901f38a2f..95974d78196397136179f8d6acf1597c557e5a23 100644 index c3e3a9950ee05dc97f15ab128e40854901f38a2f..d7eba4190110b92641664c827c6bc50f62d2ae15 100644
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
@@ -135,6 +135,13 @@ public class GameProfileCache { @@ -135,6 +135,17 @@ public class GameProfileCache {
return this.operationCount.incrementAndGet(); return this.operationCount.incrementAndGet();
} }
+ // Paper start + // Paper start
+ @Nullable public GameProfile getProfileIfCached(String name) { + @Nullable public GameProfile getProfileIfCached(String name) {
+ GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT)); + GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT));
+ return entry == null ? null : entry.getProfile(); + if (entry == null) {
+ return null;
+ }
+ entry.setLastAccess(this.getNextOperation());
+ return entry.getProfile();
+ } + }
+ // Paper end + // Paper end
+ +

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Separate lookup locking from state access in UserCache
Prevent lookups from stalling simple state access/write calls Prevent lookups from stalling simple state access/write calls
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e506480108cfbfc1 100644 index d7eba4190110b92641664c827c6bc50f62d2ae15..534373a1e305942d63ffb0fc97ea3f165eca76b5 100644
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
@@ -62,6 +62,11 @@ public class GameProfileCache { @@ -62,6 +62,11 @@ public class GameProfileCache {
@ -46,7 +46,18 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date()); calendar.setTime(new Date());
@@ -142,8 +149,9 @@ public class GameProfileCache { @@ -137,17 +144,20 @@ public class GameProfileCache {
// Paper start
@Nullable public GameProfile getProfileIfCached(String name) {
+ try { this.stateLock.lock(); // Paper - allow better concurrency
GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT));
if (entry == null) {
return null;
}
entry.setLastAccess(this.getNextOperation());
return entry.getProfile();
+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency
} }
// Paper end // Paper end
@ -57,7 +68,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1); GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1);
boolean flag = false; boolean flag = false;
@@ -159,8 +167,12 @@ public class GameProfileCache { @@ -163,8 +173,12 @@ public class GameProfileCache {
if (usercache_usercacheentry != null) { if (usercache_usercacheentry != null) {
usercache_usercacheentry.setLastAccess(this.getNextOperation()); usercache_usercacheentry.setLastAccess(this.getNextOperation());
optional = Optional.of(usercache_usercacheentry.getProfile()); optional = Optional.of(usercache_usercacheentry.getProfile());
@ -70,7 +81,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
if (optional.isPresent()) { if (optional.isPresent()) {
this.add((GameProfile) optional.get()); this.add((GameProfile) optional.get());
flag = false; flag = false;
@@ -172,6 +184,7 @@ public class GameProfileCache { @@ -176,6 +190,7 @@ public class GameProfileCache {
} }
return optional; return optional;
@ -78,7 +89,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
} }
public void getAsync(String username, Consumer<Optional<GameProfile>> consumer) { public void getAsync(String username, Consumer<Optional<GameProfile>> consumer) {
@@ -198,6 +211,7 @@ public class GameProfileCache { @@ -202,6 +217,7 @@ public class GameProfileCache {
} }
public Optional<GameProfile> get(UUID uuid) { public Optional<GameProfile> get(UUID uuid) {
@ -86,7 +97,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid);
if (usercache_usercacheentry == null) { if (usercache_usercacheentry == null) {
@@ -206,6 +220,7 @@ public class GameProfileCache { @@ -210,6 +226,7 @@ public class GameProfileCache {
usercache_usercacheentry.setLastAccess(this.getNextOperation()); usercache_usercacheentry.setLastAccess(this.getNextOperation());
return Optional.of(usercache_usercacheentry.getProfile()); return Optional.of(usercache_usercacheentry.getProfile());
} }
@ -94,13 +105,33 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
} }
public void setExecutor(Executor executor) { public void setExecutor(Executor executor) {
@@ -326,7 +341,9 @@ public class GameProfileCache { @@ -290,7 +307,7 @@ public class GameProfileCache {
JsonArray jsonarray = new JsonArray();
DateFormat dateformat = GameProfileCache.createDateFormat();
- this.getTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot
+ this.listTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot // Paper - allow better concurrency
jsonarray.add(GameProfileCache.writeGameProfile(usercache_usercacheentry, dateformat));
});
String s = this.gson.toJson(jsonarray);
@@ -330,8 +347,19 @@ public class GameProfileCache {
} }
private Stream<GameProfileCache.GameProfileInfo> getTopMRUProfiles(int limit) { private Stream<GameProfileCache.GameProfileInfo> getTopMRUProfiles(int limit) {
+ try { this.stateLock.lock(); // Paper - allow better concurrency - return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit);
return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit); + // Paper start - allow better concurrency
+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency + return this.listTopMRUProfiles(limit).stream();
+ }
+
+ private List<GameProfileCache.GameProfileInfo> listTopMRUProfiles(int limit) {
+ try {
+ this.stateLock.lock();
+ return this.profilesByUUID.values().stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit(limit).toList();
+ } finally {
+ this.stateLock.unlock();
+ }
} }
+ // Paper end
private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo entry, DateFormat dateFormat) { private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo entry, DateFormat dateFormat) {
JsonObject jsonobject = new JsonObject();

View File

@ -37,10 +37,10 @@ index c072819c1ebc772f524649c6c2f8b48d919bf805..bbe69b5b2b1b7ccd3358325c9a65e7e1
public static LongSupplier timeSource = System::nanoTime; public static LongSupplier timeSource = System::nanoTime;
public static final Ticker TICKER = new Ticker() { public static final Ticker TICKER = new Ticker() {
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
index 6349b33939909435120fdef5e506480108cfbfc1..ea739fae40e819fd82bc275c0af5c8269e12d656 100644 index 534373a1e305942d63ffb0fc97ea3f165eca76b5..e3fbada96b530784fa1de63a322b484865ed194f 100644
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
@@ -200,7 +200,7 @@ public class GameProfileCache { @@ -206,7 +206,7 @@ public class GameProfileCache {
} else { } else {
this.requests.put(username, CompletableFuture.supplyAsync(() -> { this.requests.put(username, CompletableFuture.supplyAsync(() -> {
return this.get(username); return this.get(username);