Tkinter GUI app runs slower as time goes on

你离开我真会死。 提交于 2021-01-05 04:47:53

问题


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.

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.

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 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?


回答1:


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.



来源:https://stackoverflow.com/questions/33786627/tkinter-gui-app-runs-slower-as-time-goes-on

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!