记: 高IO任务优化

背景: 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, 设备负载如图
    image.png

优化:

  • 尝试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倍, 设备负载恢复正常, 根据这个结果来看, 选择合适的睡眠时间是达到设备低负载的
    image.png
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'标识符来识别的

你可能感兴趣的:(记: 高IO任务优化)