我正在尝试优化游戏服务器以用于学习目的。我使用MongoDB作为其Java驱动程序的后端数据存储区。我正在数据库中存储玩家数据(级别,名称,当前任务),任务数据和一系列其他游戏玩法数据。每种文档类型都有自己的类类型以及相应的字段(例如User.class
包含users
集合中的文档,Quest.class
包含quests
集合中的文档等。
现在,当玩家执行某个操作时,我正在使用玩家的用户名从users
集合中查找文档并相应地进行更新。这是非常昂贵的,因为这意味着每次用户执行操作时,都需要数据库查询来获取当前播放器的数据。
当然,我的下一个想法是在连接到服务器时加载播放器的用户文档并单独存储,然后在断开连接时将其删除,并将更新的数据从内存保存到MongoDB。
问题在于我还想对所有其他集合执行类似的操作,并且这是唯一可预见的方法(因为每个缓存有不同的键来查找数据,通常是字符串和UUID)类似于以下内容:
// Create a bunch of separate caches (faster than Guava Table, but ugly)
// For example, after finding a user: userCache.put("TheirUsername", user);
private HashMap<String, User> userCache = new HashMap<>();
private HashMap<UUID, Group> groupCache = new HashMap<>();
private HashMap<Integer, Quest> questCache = new HashMap<>();
// Or use a Guava Table to store all (this is slower than individual maps)
// For example, after finding a user: cache.put(User.class, "TheirUsername", user);
private Table<Class, Object, Object> cache = HashBasedTable.create();
是否有其他方法可以拥有大量地图并将搜索结果存储在这些地图中(每个缓存集合一个)?
我希望以某种方式抽象这一点,而不会造成性能损失。我试图使用Guava实现Table<Class, Object, Object>
,以便缓存基本上是动态的,并允许我缓存任何类。问题是表格慢得多,特别是如果每秒有数百个查找......
我不确定如何在不影响代码干净性的情况下尽可能优化性能。桌子本质上是我喜欢做的,因为它非常通用,但它不够快。
答案 0 :(得分:0)
基本上,您可以使用从对象到对象的单个地图。如果你的密钥都有一个正确的equals() - 方法(所有基本的运行时类都有)你就不应该有任何问题。
因此,您问题的基本答案是:
HashMap<Object, Object> megaCache = new HashMap<>();
megaCache.put("someUser", someUserObject);
...
User cachedUser = (User) megaCache.get("someUser");
但是,我强烈建议不这样做!
你放弃了仿制药的所有美感和类型安全,并用各种东西加载一张地图。 (通常,这不是关于运行时的主要问题,但是在不相关的键类型之间发生哈希冲突的可能性会增加。)
而是选择原始帖子中的单个缓存,并且类型安全且清晰。