【发布时间】:2018-08-18 04:14:46
【问题描述】:
我有一个从 Oracle DB 获取 ResultSet 的进程,然后使用返回的数据创建对象,然后将对象添加到 Map 并最终将映射加载到内存数据网格中。我的最大结果集可能有 3000 万条记录。我注意到在处理了大约 1400 万条记录后,应用程序的速度显着降低。我有 -Xmx=12G 和 -Xms=512M。我的应用程序部署在 WebLogic 版本 12.2.0.1 和 Java 版本 8_66 上。我还注意到托管服务器产生的这条消息:
- JVM 暂停时间可能过长:
我试图弄清楚如何优化我的代码或 JVM 配置。这是代码
MyObj myObj = null;
while (rs.next()) {
myObj = new Balance(rs.getString("Field1"), rs.getString("Field2"), rs.getString("Field3"),
....
rs.getString("Field17"), rs.getString("Field18"), rs.getString("Field19"));
Map<String, Account> myMap = new HashMap<>();
myMap.put(rs.getString("FieldA"), new Account(rs.getString("FieldA"), rs.getDouble("FieldC"),
rs.getString("FieldD"), Boolean.FALSE, Boolean.FALSE));
myObj.setAccounts(myMap);
myKey = myObj.getKey();
existingObject = cacheMap.get(myKey);
if (existingObject != null) {
myObj = myObj.merge(existingObject);
}
cacheMap.put(myKey, myObj);
recCount++;
if (recCount % 250000 == 0) {
logger.info("Processed " + recCount + " records.");
}
}
【问题讨论】:
-
您是否有特定的原因需要内存中的如此大的地图?更好的策略是仅在需要时获取所需的东西。
-
这真是一个设计问题。看起来 12G 对你的程序来说是不够的,所以当垃圾收集器试图释放未使用的对象时,它卡住了,因为大多数对象仍在使用中。无论如何,如果重构为时已晚 - 您可以重新组织循环。我认为你可以改变你的
merge策略。 IE。首先在缓存映射中检查该对象,然后,如果存在,则将其他实体添加到现有映射中,而不是构建新映射并将其与现有映射合并。 -
我建议使用分析器来检查运行时发生的情况。只看代码,我猜你可能的痛点是:
rs#next、myMap#put、myObjsetAccounts、myObj#merge、cacheMap#put。
标签: java performance optimization