You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib实时子图循环耗时优化及耗时递增原因咨询

Matplotlib实时绘图性能优化与耗时递增原因解析

耗时随迭代递增的原因

  1. 线条对象持续累积:每次循环调用ax.plot()都会在坐标轴上新增一条完整曲线,而非更新已有曲线。随着迭代次数增加,轴上的历史线条数量越来越多,matplotlib每次渲染时需要处理所有这些线条,计算量线性增长,导致耗时逐步上升。
  2. 低效的列表头部删除:使用列表pop(0)删除头部元素是O(n)复杂度操作,每次删除都要移动列表中所有后续元素,迭代次数越多,该操作的累积耗时越明显。
  3. 重复的轴范围设置:每次循环都重复设置固定的y轴范围,这会触发不必要的轴布局计算,增加额外开销。

优化方案

1. 复用线条对象,避免重复创建

初始化时先绘制一次曲线,获取线条实例,后续仅更新线条的xdata和ydata,而非重新绘制整条曲线,彻底避免线条对象累积的问题。

2. 改用双端队列优化列表操作

使用collections.deque替代普通列表,其popleft()方法是O(1)复杂度,大幅提升头部元素删除的效率,且可通过maxlen自动维护数据长度,省去手动判断删除的逻辑。

3. 减少冗余的轴配置操作

固定的y轴范围仅在初始化时设置一次,无需每次循环重复调用;x轴范围按需更新即可。

4. 可选:启用高效渲染方式

使用fig.canvas.draw_idle()替代plt.draw(),该方法仅重绘需要更新的部分,比全画布重绘更高效。


优化后的完整代码

import matplotlib.pyplot as plt
import random
import time
from collections import deque

# 用deque自动维护数据长度,避免手动pop操作
x_scale = 30
x = deque(maxlen=x_scale)
y1 = deque(maxlen=x_scale)
y2 = deque(maxlen=x_scale)
i = 0

# 初始化画布与坐标轴
fig, (ax1, ax2) = plt.subplots(2, sharex=True)
fig.set_size_inches(8, 4)
ax1.set_title("top chart")
ax2.set_title("bottom chart")
ax2.set_xlabel("TIME")
ax1.set_ylabel("RND_1")
ax2.set_ylabel("RND_2")

# 固定y轴范围,仅初始化时设置
ax1.set_ylim(0, 150)
ax2.set_ylim(0, 20)

# 初始化线条对象,后续仅更新数据
line1, = ax1.plot([], [], color='b')
line2, = ax2.plot([], [], color='r')

while True:
    now = time.time()
    
    # 添加新数据,deque自动溢出旧数据
    x.append(i)
    y1.append(round(100 * random.random()))
    y2.append(round(10 * random.random()))
    
    # 更新x轴范围
    ax1.set_xlim(i - x_scale, i)
    ax2.set_xlim(i - x_scale, i)
    
    # 更新线条数据
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    
    # 仅重绘需要更新的区域
    fig.canvas.draw_idle()
    
    if plt.waitforbuttonpress(0.01):
        break
    
    now1 = time.time()
    duration = round((now1 - now) * 1000)
    print(duration)
    i += 1

内容的提问来源于stack exchange,提问作者xuraax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 18:12:28