Open GinRyan opened 4 years ago
增加城市市民样本容量会逐渐拉长每次更新UI状态的单位时间,原因是每次更新时会循环所有person的update方法,update方法中继续嵌套更多的(隐藏)循环,时间复杂度高达 O(N^2) ,更新性能随着样本容量增加(person)性能以二次方速度的降低。
增加样本容量直达5万,每次的UI内部状态更新时长严重增长10倍以上,大样本容量导致UI更新卡顿
1、UI前端当前使用swing和awt,暂时没有到达性能瓶颈。因此可暂时无需更改前端。 当前要解决的是,UI更新时消耗大量的CPU时间,因此我们可以调整为异步通知的形式,分为至少两个线程。一个线程用于UI更新,另一个线程用于大量的person行为计算,分离UI更新操作和计算操作到两个线程,互不干涉。仅仅在需要更新UI状态数据时,工作线程通过生产者-消费者模型向UI线程发送需要更新的数据消息更新UI,并且使用ConcurrentHashMap等线程安全且高效的内存容器进行数据传递。
生产者-消费者
ConcurrentHashMap
2、可以对update当中的一些耗时循环和无用循环步骤进行剪枝操作,优化成O(N)甚至更低时间复杂度,以减少CPU计算量。
建议方案的优化效果可以大幅提高样本容量以及UI更新频次,UI更新频次可以达到更高,在CPU承受范围内快速更新UI且不受到计算量增加的影响。
1、问题描述:
增加城市市民样本容量会逐渐拉长每次更新UI状态的单位时间,原因是每次更新时会循环所有person的update方法,update方法中继续嵌套更多的(隐藏)循环,时间复杂度高达 O(N^2) ,更新性能随着样本容量增加(person)性能以二次方速度的降低。
2、问题现象
增加样本容量直达5万,每次的UI内部状态更新时长严重增长10倍以上,大样本容量导致UI更新卡顿
3、建议方案
1、UI前端当前使用swing和awt,暂时没有到达性能瓶颈。因此可暂时无需更改前端。 当前要解决的是,UI更新时消耗大量的CPU时间,因此我们可以调整为异步通知的形式,分为至少两个线程。一个线程用于UI更新,另一个线程用于大量的person行为计算,分离UI更新操作和计算操作到两个线程,互不干涉。仅仅在需要更新UI状态数据时,工作线程通过
生产者-消费者
模型向UI线程发送需要更新的数据消息更新UI,并且使用ConcurrentHashMap
等线程安全且高效的内存容器进行数据传递。2、可以对update当中的一些耗时循环和无用循环步骤进行剪枝操作,优化成O(N)甚至更低时间复杂度,以减少CPU计算量。
4、优化效果
建议方案的优化效果可以大幅提高样本容量以及UI更新频次,UI更新频次可以达到更高,在CPU承受范围内快速更新UI且不受到计算量增加的影响。