背景: crontab有个周期性的大文件任务, 单文件, 大小123g, 总行数132831672, 业务上需要将该文件处理为多个压缩文件, 以便于传输; 使用下述方案实现
target_file="data/full/${date}"
line=`cat ${target_file} | wc -l`
eachline=`echo $line | awk '{print int($1/20)+5}'`
rm -rf data/split/*
split -l $eachline ${target_file} data/split/part_
cd data/split
for _file in `ls . | grep part_ | grep -v gz`
do
gzip -c ${_file} > ${_file}.gz
done
cd -
问题: 调用该脚本实现会导致服务器IO打满、操作卡顿
- 调用上述脚本仅统计
line
耗时800s, 设备负载如图
优化:
- 尝试1 使用python脚本代替linux命令, 结果如下, IO打满, 耗时略有上升, 失败
def main():
"""
main函数
"""
cnt = 0
start = time.time()
with open(sys.argv[1], 'r') as ff:
for line in ff:
cnt += 1
print (cnt, time.time() - start)
(132831672, 837.3407158851624)
-
尝试2 原有基础上, 增加sleep机制, 耗时增长8倍, 设备负载恢复正常, 根据这个结果来看, 选择合适的睡眠时间是达到设备低负载的
def main():
"""
main函数
"""
cnt = 0
start = time.time()
with open(sys.argv[1], 'r') as ff:
for line in ff:
time.sleep(1e-6)
cnt += 1
print (cnt, time.time() - start)
(132831672, 7379.751121044159)
思考:
- 无论是系统自带命令或是由其他语言实现的行数统计, 都会将整个文件全部过一遍,尚不能实现每行仅读取首字符即line[0]来做数据统计,若实现则可极大降低io流量;
- 目前文本换行是根据'\n'标识符来识别的