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();
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
index c3e3a9950ee05dc97f15ab128e40854901f38a2f..95974d78196397136179f8d6acf1597c557e5a23 100644
index c3e3a9950ee05dc97f15ab128e40854901f38a2f..d7eba4190110b92641664c827c6bc50f62d2ae15 100644
--- a/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();
}
+ // Paper start
+ @Nullable public GameProfile getProfileIfCached(String name) {
+ 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
+

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
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
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
@@ -62,6 +62,11 @@ public class GameProfileCache {
@ -46,7 +46,18 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
Calendar calendar = Calendar.getInstance();
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
@ -57,7 +68,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1);
boolean flag = false;
@@ -159,8 +167,12 @@ public class GameProfileCache {
@@ -163,8 +173,12 @@ public class GameProfileCache {
if (usercache_usercacheentry != null) {
usercache_usercacheentry.setLastAccess(this.getNextOperation());
optional = Optional.of(usercache_usercacheentry.getProfile());
@ -70,7 +81,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
if (optional.isPresent()) {
this.add((GameProfile) optional.get());
flag = false;
@@ -172,6 +184,7 @@ public class GameProfileCache {
@@ -176,6 +190,7 @@ public class GameProfileCache {
}
return optional;
@ -78,7 +89,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
}
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) {
@ -86,7 +97,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid);
if (usercache_usercacheentry == null) {
@@ -206,6 +220,7 @@ public class GameProfileCache {
@@ -210,6 +226,7 @@ public class GameProfileCache {
usercache_usercacheentry.setLastAccess(this.getNextOperation());
return Optional.of(usercache_usercacheentry.getProfile());
}
@ -94,13 +105,33 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801
}
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) {
+ 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);
+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency
- return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit);
+ // Paper start - 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) {
JsonObject jsonobject = new JsonObject();

View file

@ -37,10 +37,10 @@ index c072819c1ebc772f524649c6c2f8b48d919bf805..bbe69b5b2b1b7ccd3358325c9a65e7e1
public static LongSupplier timeSource = System::nanoTime;
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
index 6349b33939909435120fdef5e506480108cfbfc1..ea739fae40e819fd82bc275c0af5c8269e12d656 100644
index 534373a1e305942d63ffb0fc97ea3f165eca76b5..e3fbada96b530784fa1de63a322b484865ed194f 100644
--- a/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 {
this.requests.put(username, CompletableFuture.supplyAsync(() -> {
return this.get(username);