首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在AIX/bash上读取bash循环中的文件比在Linux/ksh - BLOCKSIZE中慢得多?

在AIX/bash上读取bash循环中的文件比在Linux/ksh - BLOCKSIZE中慢得多?
EN

Stack Overflow用户
提问于 2017-11-13 03:33:20
回答 2查看 317关注 0票数 1

我们有一个自定义脚本(使用ksh),它是在RHEL Linux中开发的。其功能是: 1)读取输入ASCII文件2)使用sed -i将"\“替换为"\”替换文件3)将历史文件加载到内存4)将数据与当天进行比较5)生成净变化记录

在平台升级期间,我们必须在AIX7.1上迁移此脚本,并将ksh替换为bash,因为在ksh上不能使用typeset -A,并且使用-i -pi -e执行sed perl命令时,脚本的其余部分几乎相同。

我们观察到,在Linux中,该脚本的处理时间为1小时( 691个文件),但是在AIX中,该脚本的处理时间为7+小时。

我们观察到,对于一个输入文件,以下代码片段具有性能差异,Linux代码在1-2秒内完成,而在AIX中则需要13-15秒。由于每个文件的这种性能差异,对于691个文件,脚本需要7个小时才能完成。

如果我们可以在AIX上优化这个脚本以获得更好的性能,您能帮我理解一下吗?任何指针都会非常有帮助。提前感谢您的帮助!

将测试结果添加到下面以解决更精确的问题

Linux测试脚本:

代码语言:javascript
复制
#!/bin/sh
export LANG="C"
echo `date`
typeset -A Archive_Lines
if [ -f "8249cii1.ASC" ]
then
echo `date` Starting sed
sed -i 's/\\/\\\\/g' 1577cii1.ASC
echo `date` Ending sed
while read line; do
 if [[ "${#line}" == "401" ]]
 then
 Archive_Lines["${line:0:19}""${line:27}"]="${line:27:10}"
else
echo ${#line}
fi
done < 1577cii1.ASC
echo `date` Starting sed
sed -i 's/\\\\/\\/g' 1577cii1.ASC
echo `date` Ending sed
fi
echo `date`

Linux执行:

代码语言:javascript
复制
ksh read4.sh
Sun Nov 12 15:03:18 CST 2017
Sun Nov 12 15:03:18 CST 2017 Starting sed
Sun Nov 12 15:03:19 CST 2017 Ending sed
402
405
403
339
403
403
Sun Nov 12 15:03:22 CST 2017 Starting sed
Sun Nov 12 15:03:23 CST 2017 Ending sed
Sun Nov 12 15:03:23 CST 2017

AIX测试脚本:

代码语言:javascript
复制
#!/usr/bin/bash
export LANG="C"
echo `date`
typeset -A Archive_Lines
if [ -f "1577cii1.ASC" ]
then
echo `date` Starting perl
perl -pi -e 's/\\/\\\\/g' 1577cii1.ASC
echo `date` Ending perl
while read line; do
 if [[ "${#line}" == "401" ]]
 then
 Archive_Lines["${line:0:19}""${line:27}"]="${line:27:10}"
else
echo ${#line}
 fi
done < 1577cii1.ASC
echo `date` Starting perl
perl -pi -e 's/\\\\/\\/g' 1577cii1.ASC
echo `date` Ending perl
fi
echo `date`

AIX测试执行:

代码语言:javascript
复制
  bash read_test.sh
    Sun Nov 12 15:00:17 CST 2017
    Sun Nov 12 15:00:17 CST 2017 Starting perl
    Sun Nov 12 15:00:18 CST 2017 Ending perl
    402
    405
    313
    403
    337
    403
    403
    Sun Nov 12 15:01:29 CST 2017 Starting perl
    Sun Nov 12 15:01:29 CST 2017 Ending perl
    Sun Nov 12 15:01:29 CST 2017

用echo替换Archive_Lines"${line:0:19}""${line:27}"="${line:27:10}“”。

代码语言:javascript
复制
 bash read_test.sh
Sun Nov 12 16:56:27 CST 2017
Sun Nov 12 16:56:27 CST 2017 Starting perl
Sun Nov 12 16:56:27 CST 2017 Ending perl
.
.
.
.
.
Sun Nov 12 16:56:42 CST 2017 Starting perl
Sun Nov 12 16:56:42 CST 2017 Ending perl
Sun Nov 12 16:56:42 CST 2017

使用Archive_Lines"${line:0:19}""${line:27}"="${line:27:10}“

代码语言:javascript
复制
 bash read_test.sh
Sun Nov 12 16:59:52 CST 2017
Sun Nov 12 16:59:52 CST 2017 Starting perl
Sun Nov 12 16:59:52 CST 2017 Ending perl
402
405
313
403
337
403
403
Sun Nov 12 17:01:11 CST 2017 Starting perl
Sun Nov 12 17:01:11 CST 2017 Ending perl
Sun Nov 12 17:01:11 CST 2017

谢谢,Vamsi

EN

回答 2

Stack Overflow用户

发布于 2017-11-13 07:10:28

正如沃尔特所建议的那样,看起来bash对子字符串处理(可能还有长度测试)有一些性能上的影响。

看看你在其他解决方案中得到了什么样的计时,这可能会很有趣。

下面是一个简单的awk解决方案,它应该与原始的bash/子字符串逻辑做同样的事情(使用当前的样本数据文件;不输出行长度!= 401):

代码语言:javascript
复制
awk 'length($0)==401 { print substr($0,1,20)substr($0,28)"|"substr($0,28,10) }' 1577cii1.ASC | \
while IFS="|" read idx val
do
    Archive_Lines["${idx}"]="${val}"
done

  • length($0)==401:如果行长为401,则...
  • print ...."|" ...:打印由竖线(|)分隔的2段输出/字段,其中字段为...
  • substr($0,1,20)substr($0,28):等同于您的${line:0:19}${line:27}
  • substr($0,28,10):等同于您的${line:27:10}
  • at这一点,长度为401的每一行都生成类似string1|string2
  • while IFS="|" read idx val的输出:将输入拆分为两个变量...
  • Archive_Lines["${idx}"]="${val}":使用这两个变量作为数组索引/值对

注意:添加了竖线(|)作为字段分隔符,以防子字符串可以包含空格;当然,如果子字符串可以包含竖线(|),则替换为其他字符,这些字符不会出现在子串中,并且可以用作字段分隔符。

目标是看看awk's内置的长度/子串处理是否比bash's长度/子串处理快……

票数 2
EN

Stack Overflow用户

发布于 2017-11-13 09:20:56

这解决了我的问题

代码语言:javascript
复制
#!/usr/bin/ksh93
export LANG="C"
echo `date`
typeset -A Archive_Lines
if [ -f "1577cii1.ASC" ]
then
echo `date` Starting perl
perl -pi -e 's/\\/\\\\/g' 1577cii1.ASC
echo `date` Ending perl
while read line; do
 if [[ "${#line}" == "401" ]]
 then
Archive_Lines[${line:0:19}${line:27}]="${line:27:10}"
else
echo ${#line}
 fi
done < 1577cii1.ASC
echo `date` Starting perl
perl -pi -e 's/\\\\/\\/g' 1577cii1.ASC
echo `date` Ending perl
fi
echo `date`


ksh93 read_test3.sh
Sun Nov 12 19:19:34 CST 2017
Sun Nov 12 19:19:34 CST 2017 Starting perl
Sun Nov 12 19:19:34 CST 2017 Ending perl
402
405
403
339
403
403
Sun Nov 12 19:19:38 CST 2017 Starting perl
Sun Nov 12 19:19:39 CST 2017 Ending perl
Sun Nov 12 19:19:39 CST 2017
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47253048

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档