在性能测试过程中,有时发现某个接口非常慢,此时借助监控工具,比如性能指标监控、慢查询监控、cpu监控、内存监控,还是难以精确定位到底是哪一个地方出了问题,此时就应该怀疑是否存在大量的循环调用了。举例如下:
- 对慢接口进行单步调试,发现第5行较慢
User curUser = getCurUser(request);
checkSuspend(examId, subjectId);
TopicBlockInfo topicBlockInfo = new TopicBlockInfo();
Exam examInfo = examService.getBasic(examId);
List<StatisInfo> statisInfoList = getStatisInfoList(examInfo, subjectId, curUser, TaskType.NORMAL);
topicBlockInfo.setStatisInfoList(statisInfoList);
OtherInfo otherInfo = getOtherInfo(examId, subjectId);
topicBlockInfo.setOtherInfo(otherInfo);
- 继续进入getStatisInfoList方法里面,初步分析发现两层for循环,在topicblockSettingList和teacherIds数量较多时,循环次数非常大,问题根源就在此,虽然每次service请求耗时都很短,也没有慢查询sql,但是循环调用过于频繁,导致整体响应太慢动辄20秒以上,所以需要缓存或只取所需数据,减少大量无关的调用。
for (TopicblockSetting topicblockSetting : topicblockSettingList) {
TopicSetting topicSetting = new TopicSetting();
topicSetting.setTopicIndexList(topicblockSetting.getTopicindexList());
topicSetting.setRating(topicblockSetting.getRating());
topicSetting.setTaskDispatch(topicblockSetting.getTaskDispatch());
topicSettings.add(topicSetting);
//任务量返回模式需要设置teacher及其schoolId
if (examSession.getTaskPoolDispatch() == 1 || examSession.getTaskPoolDispatch() == 2) {
List<Teacher> teacherList = new LinkedList<>();
String[] teacherIds = topicblockSetting.getMarkingTeachers().split(",");
for (String teacherId : teacherIds) {
int tId = Integer.parseInt(teacherId);
com.cosfuture.eiduo.base.school.model.Teacher t = teacherService.get(tId);
Integer sId = t.getSchool().getId();
Teacher teacher = new Teacher(tId, sId);
teacherList.add(teacher);
}
topicSetting.setMarkingTeachers(teacherList);
List<Teacher> arbitratorList = new LinkedList<>();
String arbitrators = topicblockSetting.getArbitrators();
if (!StringUtils.isBlank(arbitrators)) {
String[] arbitratorIds = arbitrators.split(",");
for (String arbitratorId : arbitratorIds) {
int tId = Integer.parseInt(arbitratorId);
com.cosfuture.eiduo.base.school.model.Teacher t = teacherService.get(tId);
Integer sId = t.getSchool().getId();
Teacher teacher = new Teacher(tId, sId);
arbitratorList.add(teacher);
}
topicSetting.setArbitrators(arbitratorList);
}
}
}