要说想追求高性能还真不能强求tkinter,实在是写得憋屈
@text_time
def highlight_render(full_match_index: deque, group_match_index: deque):
full_match_index.popleft()
group_match_index.popleft()
index_str1 = [f'1.{i}' for i in full_match_index]
index_str2 = [f'1.{j}' for j in group_match_index]
index_len1 = len(index_str1)
chunk_rest = index_len1 % 16
if len(index_str1) == 0:
return
for start in range(0, index_len1 - chunk_rest, 16):
Thread(target=area_in.tag_add, args=('tag', *index_str1[start:start + 16])).start()
else:
area_in.tag_add('tag', *index_str1[-chunk_rest:])
if len(index_str2):
area_in.tag_add('tag2', *index_str2)
如上所述这段代码,本来我还要给index_str2双端队列数据也开个线程处理的,但我写到这就打算运行一下,其中area_in是tkinter的Text文本框,我执行完代码发现Thread开启的线程居然没有任何反应。后续的代码都是正常执行。后来我在想会不会是因为不能在同一时间对tkinter的控件进行多次写入,验证后发现还真是如此。Python的Tkinter是基于事件驱动的单线程模型,没有办法做到同时多次更新。而且Text还很容易因为数据大点而崩溃,这真的有点南蚌。哎,算了,谁叫我没去学Pyqt了,这下是下定决定一定要学学Pyqt了,tkinter前前后后也写了几千行代码了,居然现在才发现这种缺陷,也说明其实基本需求大多数时候tkinter都是能胜任的。
如果你想问难道性能瓶颈就在此处了吗?的确如此,渲染的队列经过了充分去重优化,就是为了让渲染的数据尽可能少,然而效果仍然不佳啊!
函数collect_result 花费时间0.0064949000952765346s
highlight_render函数花费时间0.00031079992186278105s
restore函数花费时间0.016018100082874298s
choose_mode函数花费时间0.024405700038187206s
这是将渲染的那步注释掉后的结果,choose_mode是主函数,结果用时仅仅为0.024s,去除注释后,再看着highlight_render函数:
函数collect_result 花费时间0.006642199936322868s
highlight_render函数花费时间0.1525147999636829s
restore函数花费时间0.08116679999511689s
choose_mode函数花费时间0.24182719993405044s
好家伙,不仅highlight_render的耗时直线飙升,连restore函数也出现了显著的耗时增加。不得不说这个程序的确是完全受限于tkinter了,感觉已经没有任何优化空间了。当然如果用C++来重写一些函数可能可以更快一些,但我还是希望原生态一点。