设为首页 收藏本站
查看: 2327|回复: 6

[经验分享] 一个 Shell 程序的性能优化

[复制链接]

尚未签到

发表于 2012-7-4 15:22:41 | 显示全部楼层 |阅读模式
简介: 编写 Linux Shell 脚本程序不要仅限于完成基本的程序功能,认真的分析 Shell 脚本并找出优化的方法对个人能力的提高以及对脚本程序的质量改善都有重要的意义,希望读者能从本文中获得许多实用的 Shell 程序方法。
[size=0.76em]问题描述:有一个普通的通话话单文件(包括"计费号码","主叫号码","被叫号码","开始时间","结束时间","时长","费用"等其它字段),要求根据另外一个号段配置文件(由"号段下限"和"号段上限"两个字段组成)将此话单文件进行分拣过虑。
[size=0.76em]分拣规则:如果通话话单文件中的"计费号码"位于号段文件的某个号段内,则将此条记录计入结果文件 1,否则计入结果文件 2。
[size=0.76em]通话话单文件样例:

9013320003|9013320003|9918128025|20060814163420|20060814163450|30|20|00|01|0059926645208|9926645208|9918188065|20060814163415|20060814163545|90|30|00|01|0059934877207|9934877207|9936972003|20060814163620|20060814163930|190|50|00|01|005............

[size=0.76em]号段配置文件样例:

9013305000,90133279999013767000,90137689999923670000,99236799999928998000,99289999999932310000,99323199999932333400,99323335999936034000,99360369999936084000,99360849999998537000,99985379999998620000,99986299999998690000,9998699999

[size=0.76em]例如:
[size=0.76em]对于通话话单文件的第一条记录中的"计费号码"为 9013320000,此号码正好属于号段配置文件的第一个号段 9013305000,9013327999中,即:条件 9013305000<= 9013320000 <=9013327999 成立,所以应该将通话话单文件的第一条记录计入结果文件 1 中;对于通话话单文件中的第二条记录的"计费号码"为 9926645208 它不属于号段文件中的任何一个段,所以应该将通话话单的第二条记录计入结果文件 2 中。
[size=0.76em]对于这样一个简单的问题首先想到的解决方法为:
[size=0.76em]解决方法1:
[size=0.76em]写一个双重循环,外层循环为逐条读取"通话话单文件"并获取每条记录的第一个字段的值"计费号码",内层循环:根据外层循环获得的"计费号码"在"号段文件"中循环比较,判断此号码是否属于相应号段。
[size=0.76em]程序代码如下(省略了文件存在性判断等语句):

while read fdoorg="$(expr substr ${f} 1 10)"   #取得"计费号码"存入变量org中while read numsegdonglow="$(expr substr ${numseg} 1 10 )"   #将号段下限存入变量nglowngtop="$(expr substr ${numseg} 12 10 )"  #将号段上限存入变量ngtopif [ "$org" \> "$nglow"  -a "$org" \< $ngtop ]#判断"计费号码"是否在此号段内thenecho "${f}" >> ./resultfile1.cdr #如果在此号段内,将此记录计入结果文件1中else echo "${f}" >> ./resultfile2.cdr #如果不在此号段内,将此记录计入结果文件2中fidone < ./numseg.txtdone < ./rttest.txt

[size=0.76em]解决方法1 对于号段文件和通话话单的记录数都比较少的情况下基本可以完成工作,但是当两个文件的记录数较多(例如号段文件>50条,话单文件>10000条)的时候,这种方法就会花费几个小时甚至几天的时间才能得出处理结果。此脚本程序执行慢的原因是对第二个循环内的比较运算只用了最简单的顺序比较方法,所以当号段文件的记录增多的时候,脚本的执行速度会急剧下降。
[size=0.76em]解决方法2:
[size=0.76em]将内层循环的逐个比较的方法改为二分查找法进行判断,程序代码如下:

#!/bin/bash#Author Xsh  date:08-15-2006#程序中使用了二分查找法进行号码的范围判断#为突出重点,省略了文件存在性判断和异常捕获以及帮助提示等程序语句#程序的工作目录为当前目录echo "Time:$(date)==>Strat to processing........." #显示程序开始运行时间while read numsegdotmplow="${tmplow} $(expr substr ${numseg} 1 10 & >/dev/null ) "tmptop="${tmptop} $(expr substr ${numseg} 12 10 & >/dev/null ) "done < ./numseg.txt#读取号段文件,下限号段存入变量tmplow,上限号段存入变量tmptoparr_lownug=(${tmplow}) #将下限号段存入数组arr_lownugarr_topnug=(${tmptop})        #将上限号段存入数组arr_topnug#定义函数checknum(),输入参数为需要检查的"计费号码",输出参数为0或者1#若checknum()输出为0 表示"计费号码" 不在号段文件的所有号段范围内#若checknum()输出为1 表示"计费号码" 在号段文件的所有号段范围内# checknum()函数中用二分搜索法进行号码的判断checknum(){thisnum=$1ckresult=0lowflag=0topflag=$(expr ${#arr_lownug
  • } - 1 )  #标注1MaxIndex=$(expr ${#arr_topnug
  • } - 1 ) #标注2midflag=0midflag=$(expr ${topflag} / 2 )                #标注3if [ "${thisnum}" \< "${arr_lownug[0]}" -o "${thisnum}" \>"${arr_topnug[${MaxIndex}]}"  ]thenreturn 0elsewhile [ "$lowflag" != "$midflag" ]doif[ "$thisnum" \> "${arr_lownug[${midflag}]}" -o "$thisnum" == \"${arr_lownug[${midflag}]}" ]thenlowflag=${midflag}midflag=$(expr `expr ${topflag} + ${lowflag}` / 2 ) #标注4elif["$thisnum"\<"${arr_lownug[${midflag}]}" -o "$thisnum" == \"${arr_lownug[${midflag}]}" ] thentopflag=${midflag}midflag=$(expr `expr ${topflag} + ${lowflag}` / 2 ) #标注5elseecho "Error!"   fidone if [ "$thisnum" \< "${arr_topnug[${lowflag}]}" -o "$thisnum" == \"${arr_topnug[${lowflag}]}" ]thenreturn 1else return 0 fifi}#函数定义完毕while read fdoorg="$(expr substr ${f} 1 10)" #标注6checknum ${org}returnval=$?if [ "$returnval" == "1"  ]then echo "${f}" >> ./Match_result.cdr  #将匹配的记录存入结果文件1elseecho "${f}" >> ./NoMatch_result.cdr #将不匹配的记录存入结果文件2fidone < ./rttest.txt echo "Time:$(date) ==> Proccess is end! "exit 0;

  • [size=0.76em]将以上程序投入运行,号段文件有 71行记录,需要分拣的通话话单文件17 万条左右通过观察发现此方法的执行效率确实比解决方法1 提高了很多,但是仍需要数小时的时间 才能执行完毕。我另外写了一个同样功能的C语言程序,执行同样的测试数据得出结果仅需要10~15秒的时间!shell 程序确实要比同样功能的C程序慢一些,但是目前的情况是用C程序处理只需要几秒钟时间, 而Shell程序确需要数小时!在用此Shell程序处理的时候我用Top命令看了一些系统资源的消耗发现CPU、内存以及IO的占用都极小,说明系统资源很充足,不是系统的问题造成了程序处理速度慢。问题出在哪了呢?
    [size=0.76em]我用命名ps -ef 观察系统进程的运行情况,发现每过几秒种就会有一个expr进程产生, 这个进程运行很短的时间就消失了(不仔细观察可能都看不到有expr这个进程产生)。这时 候我觉得我好像发现程序运行慢的原因了:程序的几个循环里面都有用expr进行计算的语句,expr属于Shell外部命令,所以每次运算都要产生一个expr进程,而程序的运行种最消耗时间的除了IO操作外就数产生新进程操作了,于是我决定把用expr进行计算的地方都尽量修改为用shell的内部命令进行计算。程序变成了下面的样子(标注1~标注6为修改过的地方):
    [size=0.76em]程序代码如下:

    ―――――――――――――――――――――――――――――――――――――――#!/bin/bash#Author Xsh  date:08-15-2006echo "Time:$(date)==>Strat to processing........." #显示程序开始运行时间while read numseg          do           tmplow="${tmplow} $(expr substr ${numseg} 1 10 & >/dev/null ) "            tmptop="${tmptop} $(expr substr ${numseg} 12 10 & >/dev/null ) "done < ./numseg.txt        #循环读取号段文件下限号段存入变量tmplow,上限号段存入变量tmptoparr_lownug=(${tmplow}) #将下限号段存入数组arr_lownugarr_topnug=(${tmptop})        #将上限号段存入数组arr_topnug#定义函数checknum(),输入参数为需要检查的"计费号码",输出参数为0或者1#函数checknum()输出为0 表示"计费号码" 不在号段文件的所有号段范围内#函数checknum()输出为1 表示"计费号码" 在号段文件的所有号段范围内#函数checknum()中用二分搜索法进行号码的判断checknum(){ #函数定义开始   thisnum=$1   ckresult=0   lowflag=0   topflag=$((${#arr_lownug
  • } - 1 ))   #标注1   MaxIndex=$((${#arr_topnug
  • } - 1 ))  #标注2   midflag=0   midflag=$((${topflag} / 2 ))              #标注3if [ "${thisnum}" \< "${arr_lownug[0]}" -o "${thisnum}" \> "${arr_topnug[${MaxIndex}]}" ]then        return 0elsewhile [ "$lowflag" != "$midflag" ]do if ["$thisnum"\> "${arr_lownug[${midflag}]}" -o "$thisnum" == \  "${arr_lownug[${midflag}]}"]   then   lowflag=${midflag}   midflag=$(( $((${topflag} + ${lowflag})) / 2 )) #标注4elif["$thisnum"\<"${arr_lownug[${midflag}]}" -o "$thisnum" == \"${arr_lownug[${midflag}]}"] then         topflag=${midflag}     midflag=$(($((${topflag} + ${lowflag})) / 2 )) #标注5else  echo "Error!"   fidone if ["$thisnum" \< "${arr_topnug[${lowflag}]}" -o "$thisnum" == \"${arr_topnug[${lowflag}]}"]then return 1else  return 0 fifi}#函数定义结束while read fdoorg="${f:0:10}"  #标注6checknum ${org}returnval=$?if [ "$returnval" == "1"  ]then echo "${f}" >> ./Match_result.cdr  #将匹配的记录存入结果文件1elseecho "${f}" >> ./NoMatch_result.cdr #将不匹配的记录存入结果文件2fidone < ./rttest.txt echo "Time:$(date) ==> Proccess is end! "exit 0;

  • 运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-462-1-1.html 上篇帖子: MySQL数据库性能优化之缓存参数优化 下篇帖子: 服务器性能优化配置建议 优化 程序
    发表于 2013-3-13 22:04:02 | 显示全部楼层
    找到好贴不容易,我顶你了,谢了

    运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    发表于 2013-5-15 22:45:29 | 显示全部楼层
    怀揣两块,胸怀500万!

    运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    尚未签到

    发表于 2013-5-16 04:04:59 | 显示全部楼层
    自从我变成了狗屎,就再也没有人踩在我头上了。

    运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    尚未签到

    发表于 2013-5-16 14:35:25 | 显示全部楼层
    男人靠的住,母猪能上树!

    运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    累计签到:1 天
    连续签到:1 天
    发表于 2013-5-16 21:04:27 | 显示全部楼层
    所有的男人生来平等,结婚的除外。

    运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    尚未签到

    发表于 2013-5-17 07:12:18 | 显示全部楼层
    勿以坑小而不灌,勿以坑大而灌之。

    运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    扫码加入运维网微信交流群X

    扫码加入运维网微信交流群

    扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

    扫描微信二维码查看详情

    客服E-mail:kefu@iyunv.com 客服QQ:1061981298


    QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


    提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


    本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



    合作伙伴: 青云cloud

    快速回复 返回顶部 返回列表