问题
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