随着时间的推移,Tkinter GUI 应用程序运行速度变慢 [英] Tkinter GUI app runs slower as time goes on

查看:41
本文介绍了随着时间的推移,Tkinter GUI 应用程序运行速度变慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计一个图形用户界面,用于显示给定周期节点上的数据包数量.程序每次循环都会向计数器添加一个,并使用新信息更新 GUI,以便每约 0.1 秒 GUI 绘制不同的布局.

I am designing a GUI that shows the number of packets on a node at a given cycle. The program adds one to the counter every loop and updates the GUI with the new info, so that every ~0.1 seconds a different layout is drawn by the GUI.

有 7 种不同的布局,当程序到达布局 7 时,它又回到 0,从而创建了 7 种布局的无限循环.这是有意的.

There are 7 different layouts, and when the program gets to layout 7 it goes back to 0, creating an infinite loop of the 7 layouts. This is intended.

问题是程序随着时间的推移运行速度变慢,即从 0 到 1 需要大约 0.101 秒,从 1 到 2 稍微慢一点,但是到第 10 次运行时,肉眼明显变慢,到 7 个布局的第 100 次运行时,从一个布局到下一个布局大约需要 1 秒.

The problem is the program runs slower as time goes on, i.e. it takes about 0.101 seconds to increment from 0 to 1 and slightly slower from 1 to 2, but by the 10th run-through it is noticeably slower to the naked eye, and by the 100th run-through of the 7 layouts it takes about 1 second to go from one layout to the next.

是否发生内存泄漏?我已经在下面发布了动画功能:

Is there memory leak occuring? I have posted the animate function below:

def animate(i):
    global current_cycle
    global LAST_CYCLE
    global PACKETS
    global text
    global e
    global fixed_positions
    global G
    global tree
    global curr_cycle_array

    #print(e.get())

    #a.clear()
    print("current cycle is",current_cycle)

    #initialize and zero array of size (dim1*dim2)

    fixed_nodes = fixed_positions.keys()
    pos=nx.spring_layout(G,pos=fixed_positions, fixed = fixed_nodes)


    iterator = 0
    curr_cycle_array=[0] * 64

    #move through current router list and increment for each
    while(iterator<PACKETS):
        #test if packet cycle matches cycle to be displayed
        if(cycleList[iterator]==current_cycle):
            #increments curr_cycle_array for each router in the cycle
            array_var=curr_routerList[iterator]
            curr_cycle_array[array_var]=curr_cycle_array[array_var]+1

        iterator=iterator+1

    update_tree()

    #find max value of the color array for current cycle
    MAX_VALUE=curr_cycle_array[0]
    x=list(range(0,64))
    for i in x:
        if curr_cycle_array[i] > MAX_VALUE:
            MAX_VALUE=curr_cycle_array[i]

    my_color_dict={}
    #heat map for current cycle
    b=list(range(0,64))

    for c in b:
        if(MAX_VALUE==0):
           my_color_dict[c]= 'none'
        elif (0.95*MAX_VALUE <= curr_cycle_array[c] & curr_cycle_array[c] <= MAX_VALUE):
            my_color_dict[c] = 'max'
        elif (0.75*MAX_VALUE <= curr_cycle_array[c] & curr_cycle_array[c] < 0.95*MAX_VALUE):
            my_color_dict[c] = 'high'
        elif (0.65*MAX_VALUE <= curr_cycle_array[c] & curr_cycle_array[c] < 0.75*MAX_VALUE):
            my_color_dict[c] = 'medium_high'
        elif (0.55*MAX_VALUE <= curr_cycle_array[c] & curr_cycle_array[c] < 0.65*MAX_VALUE):
            my_color_dict[c] = 'medium'
        elif (0.45*MAX_VALUE <= curr_cycle_array[c] & curr_cycle_array[c] < 0.55*MAX_VALUE):
            my_color_dict[c] = 'medium_low'
        elif (0.35*MAX_VALUE <= curr_cycle_array[c] & curr_cycle_array[c] < 0.45*MAX_VALUE):
            my_color_dict[c] = 'low'
        elif (0.25*MAX_VALUE  <= curr_cycle_array[c] & curr_cycle_array[c] < 0.35*MAX_VALUE):
            my_color_dict[c] = 'very_low'
        elif (0.10*MAX_VALUE <= curr_cycle_array[c] & curr_cycle_array[c] < 0.25*MAX_VALUE):
            my_color_dict[c] = 'very_very_low'
        elif (0 == curr_cycle_array[c] | curr_cycle_array[c] < 0.10*MAX_VALUE):
            my_color_dict[c] = 'none'

        c=c+1




    #every node in G has a 'router' var for color and a 'num_packets' var for number of packets
    for node in G.nodes():
        G.node[node]['router'] = my_color_dict[node]
        G.node[node]['num_packets'] = 8

    color_map={'none':'b','very_very_low':'lightblue','very_low':'lightgreen','low':'y','medium':'orange','medium_high':'tomato','high':'r','max':'w'}

    plt.subplot(221)
    nx.draw_networkx_nodes(G,pos,node_shape='s',node_size=250,node_color=[color_map[G.node[node]['router']] for node in G.nodes()])
    nx.draw_networkx_edges(G,pos)
    #nx.draw_networkx_labels(G,pos)

    if current_cycle == LAST_CYCLE:
        current_cycle=0
    elif current_cycle < LAST_CYCLE:
        current_cycle+=1

全局变量调用会导致这个吗?正在使用的任何系统调用是否存在任何已知问题?谁有想法?这是主要的动画循环:

Could the global variable calls be causing this? Are there any known issues with any of the system calls being used? Anyone have any ideas? Here is the main animation loop:

#initialize the application
app = Application()
#begin animating the function every interval
ani = animation.FuncAnimation(f,animate,interval=100)
#allows the program to read 
app.mainloop()

FuncAnimation 按照典型的 GUI 代码一遍又一遍地调用.我想根本问题是为什么随着时间的推移,相同的代码被一遍又一遍地执行速度变慢?

FuncAnimation is called over and over again, as per typical GUI code. I guess the root problem is why is the same code being executed over and over slowing down as time goes on?

推荐答案

在 Tk 的核心(以及 Tkinter)中有一些地方可能会泄漏一些东西,因为一些关键字符串是实习生的.随着时间的推移处理大量画布项目时,重用旧项目而不是删除和创建新项目非常重要.对于线和多边形(对绘图很有用)之类的东西,这导致需要配置坐标列表,而不仅仅是制作新东西.确切地解释什么会触发这种实习泄漏并非易事(正确的解决方法是完全摆脱实习,但这是很多工作)尤其是当来自 Tkinter 时,因为泄漏的字符串实际上都是内部的Tkinter 实现及其与底层 Tk 库的耦合方式.

There are a few places where you can leak things in the core of Tk (and hence in Tkinter) because some key strings are interned. It's important when you're dealing with very large numbers of canvas items over time to reuse old items instead of deleting and creating fresh. For things like lines and polygons (which useful for graphing) this results in needing configure the coordinate list instead of just making new things. Explaining exactly what things will trigger this interning leak is not trivial (and the right fix would be to get rid of the interning entirely, but that's a lot of work) especially when coming from Tkinter, as the strings being leaked are virtually all internal to the Tkinter implementation and how it couples to the underlying Tk library.

另一方面,如果您可以避免在可能的情况下创建新项目(如有必要,您可以随时将它们隐藏起来),您应该会发现您可以在一秒钟内推送大量更新而不会影响性能.

On the other hand, if you can avoid creating new items where possible (you can always hide them out of the way if necessary), you should find that you can push very large numbers of updates through a second without any performance hit.

这篇关于随着时间的推移,Tkinter GUI 应用程序运行速度变慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆