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

标签 linux bash performance aix

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

在平台升级期间,我们必须在 AIX 7.1 上迁移此脚本,并且 用 bash 替换了 ksh,因为 typeset -A 在 ksh AIX 上不可用,sed -i 命令用 perl -pi -e 并且脚本的其余部分几乎相同。

我们观察到该脚本在 Linux 中处理了 1 小时(691 个文件),但在 AIX 中它花费了 7 个多小时。

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

能否请您帮助我了解我们是否可以调整此脚本以在 AIX 上获得更好的性能。任何指针都会非常有帮助。 预先感谢您的帮助!

在下面添加测试结果以获得更精确的问题

Linux 测试脚本:

#!/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 执行:

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 测试脚本:

#!/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 测试执行:

  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

将 Archive_Lines["${line:0:19}""${line:27}"]="${line:27:10}"替换为 echo"."

 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}"

 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

谢谢, 万西

最佳答案

正如 Walter 所建议的那样,看起来 bash 中的子字符串处理(可能还有长度测试)有一些性能问题。

可能有兴趣了解您使用其他解决方案获得的时间类型。

这是一个简单的 awk 解决方案,它应该做与原始 bash/substring 逻辑相同的事情(使用您当前的示例数据文件;没有行长度的输出!= 401):

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 那么 ...
  • 打印 ...."|"... : 打印由管道 (|) 分隔的输出/字段的 2 部分,其中字段是 ...
  • substr($0,1,20)substr($0,28) :相当于你的 ${line:0:19}${line:27}
  • substr($0,28,10) :相当于你的 ${line:27:10}
  • 此时每行长度为 401 的输出都像 string1|string2
  • 同时 IFS="|"读取 idx val:将输入拆分回 2 个变量 ...
  • Archive_Lines["${idx}"]="${val}" :使用 2 个变量作为数组索引/值对

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

目标是查看awk 的 内置长度/子字符串处理是否比bash 的 长度/子字符串处理更快...

关于linux - 在 AIX/bash 上以 bash 循环读取文件比在 Linux/ksh 中慢得多 - BLOCKSIZE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47253048/

相关文章:

linux - 在后台启动脚本时,我有两个进程正在运行

linux - tr 命令 - 如何将字符串 "\n"替换为实际的换行符 (\n)

linux - linux 中的 shuf 命令

bash - 在具有非连续索引的关联数组中查找重复元素

java - Scala:如何进行字符串连接以避免 GC 开销问题

c - 谁能给我最新的netlink编程样例?

python - 如何安装pysqlite?

bash - 在 shell 脚本中使用分隔符进行 grep

C++:删除与免费和性能

database - SQL Server 2008 CPU 使用率高