You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-20 07:26:18 +00:00
🆙 Database performance fixes
1. HabboManager - O(1) username lookup Before: getHabbo(String) held a synchronized lock and iterated ALL online users every call After: Secondary ConcurrentHashMap<String, Habbo> keyed by lowercase username → instant get() lookup, no lock contention 2. ItemsComponent - Batch DB saves Before: dispose() spawned a separate thread per dirty item, each opening its own DB connection After: Single connection, JDBC addBatch()/executeBatch() for both UPDATE and DELETE, flushed every 100 items. A user with 500 dirty items now does 5 batch executions instead of 500 thread spawns + 500 connections. 3. AcceptFriendRequestEvent - N+1 elimination Before: For each offline user: query 1 (getOfflineHabboInfo by ID) → query 2 (load full Habbo by username) = 2 queries × up to 100 users = 200 queries After: Single query by user ID directly = 1 query × up to 100 users = 100 queries (50% reduction) 4. RoomManager - Direct HashMap lookup Before: getCategory(int id) iterated all categories checking getId() == id even though the map is already keyed by ID After: Direct roomCategories.get(id) → O(1) instead of O(n)
This commit is contained in:
@@ -179,12 +179,7 @@ public class RoomManager {
|
||||
}
|
||||
|
||||
public RoomCategory getCategory(int id) {
|
||||
for (RoomCategory category : this.roomCategories.values()) {
|
||||
if (category.getId() == id)
|
||||
return category;
|
||||
}
|
||||
|
||||
return null;
|
||||
return this.roomCategories.get(id);
|
||||
}
|
||||
|
||||
public RoomCategory getCategory(String name) {
|
||||
@@ -220,15 +215,8 @@ public class RoomManager {
|
||||
}
|
||||
|
||||
public boolean hasCategory(int categoryId, Habbo habbo) {
|
||||
for (RoomCategory category : this.roomCategories.values()) {
|
||||
if (category.getId() == categoryId) {
|
||||
if (category.getMinRank() <= habbo.getHabboInfo().getRank().getId()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
RoomCategory category = this.roomCategories.get(categoryId);
|
||||
return category != null && category.getMinRank() <= habbo.getHabboInfo().getRank().getId();
|
||||
}
|
||||
|
||||
public THashMap<Integer, RoomCategory> getRoomCategories() {
|
||||
|
||||
@@ -35,11 +35,13 @@ public class HabboManager {
|
||||
public static boolean NAMECHANGE_ENABLED = false;
|
||||
|
||||
private final ConcurrentHashMap<Integer, Habbo> onlineHabbos;
|
||||
private final ConcurrentHashMap<String, Habbo> onlineHabbosByName;
|
||||
|
||||
public HabboManager() {
|
||||
long millis = System.currentTimeMillis();
|
||||
|
||||
this.onlineHabbos = new ConcurrentHashMap<>();
|
||||
this.onlineHabbosByName = new ConcurrentHashMap<>();
|
||||
|
||||
LOGGER.info("Habbo Manager -> Loaded! ({} MS)", System.currentTimeMillis() - millis);
|
||||
}
|
||||
@@ -80,10 +82,12 @@ public class HabboManager {
|
||||
|
||||
public void addHabbo(Habbo habbo) {
|
||||
this.onlineHabbos.put(habbo.getHabboInfo().getId(), habbo);
|
||||
this.onlineHabbosByName.put(habbo.getHabboInfo().getUsername().toLowerCase(), habbo);
|
||||
}
|
||||
|
||||
public void removeHabbo(Habbo habbo) {
|
||||
this.onlineHabbos.remove(habbo.getHabboInfo().getId());
|
||||
this.onlineHabbosByName.remove(habbo.getHabboInfo().getUsername().toLowerCase());
|
||||
}
|
||||
|
||||
public Habbo getHabbo(int id) {
|
||||
@@ -91,14 +95,7 @@ public class HabboManager {
|
||||
}
|
||||
|
||||
public Habbo getHabbo(String username) {
|
||||
synchronized (this.onlineHabbos) {
|
||||
for (Map.Entry<Integer, Habbo> map : this.onlineHabbos.entrySet()) {
|
||||
if (map.getValue().getHabboInfo().getUsername().equalsIgnoreCase(username))
|
||||
return map.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return this.onlineHabbosByName.get(username.toLowerCase());
|
||||
}
|
||||
|
||||
public Habbo loadHabbo(String sso) {
|
||||
@@ -178,11 +175,9 @@ public class HabboManager {
|
||||
}
|
||||
|
||||
public void sendPacketToHabbosWithPermission(ServerMessage message, String perm) {
|
||||
synchronized (this.onlineHabbos) {
|
||||
for (Habbo habbo : this.onlineHabbos.values()) {
|
||||
if (habbo.hasPermission(perm)) {
|
||||
habbo.getClient().sendResponse(message);
|
||||
}
|
||||
for (Habbo habbo : this.onlineHabbos.values()) {
|
||||
if (habbo.hasPermission(perm)) {
|
||||
habbo.getClient().sendResponse(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,14 +159,63 @@ public class ItemsComponent {
|
||||
}
|
||||
|
||||
if (!this.items.isEmpty()) {
|
||||
for (int i = this.items.size(); i-- > 0; ) {
|
||||
try {
|
||||
items.advance();
|
||||
} catch (NoSuchElementException e) {
|
||||
break;
|
||||
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) {
|
||||
try (PreparedStatement updateStmt = connection.prepareStatement(
|
||||
"UPDATE items SET user_id = ?, room_id = ?, wall_pos = ?, x = ?, y = ?, z = ?, rot = ?, extra_data = ?, limited_data = ? WHERE id = ?")) {
|
||||
try (PreparedStatement deleteStmt = connection.prepareStatement(
|
||||
"DELETE FROM items WHERE id = ?")) {
|
||||
|
||||
int updateCount = 0;
|
||||
int deleteCount = 0;
|
||||
|
||||
for (int i = this.items.size(); i-- > 0; ) {
|
||||
try {
|
||||
items.advance();
|
||||
} catch (NoSuchElementException e) {
|
||||
break;
|
||||
}
|
||||
|
||||
HabboItem item = items.value();
|
||||
if (item.needsDelete()) {
|
||||
deleteStmt.setInt(1, item.getId());
|
||||
deleteStmt.addBatch();
|
||||
deleteCount++;
|
||||
item.needsUpdate(false);
|
||||
item.needsDelete(false);
|
||||
} else if (item.needsUpdate()) {
|
||||
updateStmt.setInt(1, item.getUserId());
|
||||
updateStmt.setInt(2, item.getRoomId());
|
||||
updateStmt.setString(3, item.getWallPosition());
|
||||
updateStmt.setInt(4, item.getX());
|
||||
updateStmt.setInt(5, item.getY());
|
||||
updateStmt.setDouble(6, item.getZ());
|
||||
updateStmt.setInt(7, item.getRotation());
|
||||
updateStmt.setString(8, item.getExtradata());
|
||||
updateStmt.setString(9, item.getLimitedStack() + ":" + item.getLimitedSells());
|
||||
updateStmt.setInt(10, item.getId());
|
||||
updateStmt.addBatch();
|
||||
updateCount++;
|
||||
item.needsUpdate(false);
|
||||
}
|
||||
|
||||
if (updateCount > 0 && updateCount % 100 == 0) {
|
||||
updateStmt.executeBatch();
|
||||
}
|
||||
if (deleteCount > 0 && deleteCount % 100 == 0) {
|
||||
deleteStmt.executeBatch();
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteCount % 100 != 0) {
|
||||
deleteStmt.executeBatch();
|
||||
}
|
||||
if (updateCount % 100 != 0) {
|
||||
updateStmt.executeBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (items.value().needsUpdate())
|
||||
Emulator.getThreading().run(items.value());
|
||||
} catch (SQLException e) {
|
||||
LOGGER.error("Caught SQL exception during batch item save", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-13
@@ -3,7 +3,6 @@ package com.eu.habbo.messages.incoming.friends;
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.messenger.Messenger;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboInfo;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
import com.eu.habbo.messages.outgoing.friends.FriendRequestErrorComposer;
|
||||
import org.slf4j.Logger;
|
||||
@@ -14,7 +13,6 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import static com.eu.habbo.habbohotel.users.HabboManager.getOfflineHabboInfo;
|
||||
|
||||
public class AcceptFriendRequestEvent extends MessageHandler {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AcceptFriendRequestEvent.class);
|
||||
@@ -44,18 +42,10 @@ public class AcceptFriendRequestEvent extends MessageHandler {
|
||||
Habbo target = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId);
|
||||
|
||||
if(target == null) {
|
||||
HabboInfo habboInfo = getOfflineHabboInfo(userId);
|
||||
|
||||
if(habboInfo == null) {
|
||||
this.client.sendResponse(new FriendRequestErrorComposer(FriendRequestErrorComposer.TARGET_NOT_FOUND));
|
||||
this.client.getHabbo().getMessenger().deleteFriendRequests(userId, this.client.getHabbo().getHabboInfo().getId());
|
||||
continue;
|
||||
}
|
||||
|
||||
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT users.*, users_settings.block_friendrequests FROM users INNER JOIN users_settings ON users.id = users_settings.user_id WHERE username = ? LIMIT 1")) {
|
||||
statement.setString(1, habboInfo.getUsername());
|
||||
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT users.*, users_settings.block_friendrequests FROM users INNER JOIN users_settings ON users.id = users_settings.user_id WHERE users.id = ? LIMIT 1")) {
|
||||
statement.setInt(1, userId);
|
||||
try (ResultSet set = statement.executeQuery()) {
|
||||
while (set.next()) {
|
||||
if (set.next()) {
|
||||
target = new Habbo(set);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user