程序中每个点,都要测试其执行时间。以优化整体程序的效率
关键点:
- io操作:文件读写
- 复杂计算:数据聚合
- 算法空间/时间效率,数据结构是否合理
大文件读写
- 尽量选择列式存储方式,可以减少io,比如parquet文件。但要注意,列式存储方式,只能全量读写文件,数据量太大时,可以考虑分为多个小文件。
- 如果选择行式存储方式,比如excel文件。要考虑使用文件追加的方式写入,按批方式分别读入。
- java nio多路复用读写
多个异步任务,使用协程、多线程/多进程处理,线程优先。多线程/多进程使用时注意事项
- io性任务,优先考虑协程处理
- 尽量使用各编程语言自带的线程池、进程池,来对多线程/多进程的管理
- python语言对线程的限制
time_delta = datetime.timedelta(days=30)
months = math.ceil((finish - begin)*1.0/time_delta)
with Pool(min(4,os.cpu_count(),max(len(ts,months))) as pool:
pass
子任务中,要对异常信息进行捕获,告知主线程/进程当前任务的状态,防止主线程/进程,一直在等待子任务。另外,主线程/进程中最好也设置等待子任务的超时时间,考虑双重保证。
#子任务函数
def packonesecfile(q,*args):
try:
# 业务代码
except:
# 异常信息
finally:
# 消息放入队列
q.put(t)
#主函数
time1 = time.time()
while q.qsize()<len(ts):
time.sleep(0.5)
#保存进度告诉前端
pj['rate'] = q.qsize()/len(ts)
with open(file_path,'w') as f:
f.write(pj)
# wait timeout
if time.time()-time1 > 600:
logging.exception(f'...... wait more than 10 minutes:')
break
异步任务全部结束后,注意进程/线程池要shutdown。防止子进程一直存在,额外消耗内存。
#一个with语句,代表一个上下文context。 with语句代码块执行完,pool自动shutdown
with Pool(min(4,os.cpu_count(),max(len(ts,months))) as pool:
pass
进程/线程池shutdown之前,一定要等待子任务全部结束,否则为执行完的任务强制结束。
有几种方式
- 使用future wait
- 使用pool close and join两个方法结合。close是修改线程池状态,不再接收新的任务。join是等待线程/进程状态变为terminal
- 使用队列,自己while loop设置超时。 如上示例
算法&数据结构优化
- 多学习优秀代码、多思考、多总结。经验活