【问题标题】:Shell script vs C performanceShell 脚本与 C 性能
【发布时间】:2012-10-16 19:55:24
【问题描述】:

我想知道从 C 迁移到 shell 脚本的程序的性能会有多糟糕。

我有密集的 I/O 操作。

例如,在 C 语言中,我有一个从文件系统文件读取并写入另一个文件的循环。我在没有任何一致关系的情况下选取每条线的一部分。我正在使用指针来执行此操作。一个非常简单的程序。

在Shell 脚本中,为了移动一行,我使用${var:(char):(num_bytes)}。处理完每一行后,我只需将其连接到另一个文件。

"$out" >> "$filename"

该程序执行以下操作:

while read line; do
    out="$out${line:10:16}.${line:45:2}"
    out="$out${line:106:61}"
    out="$out${line:189:3}"
    out="$out${line:215:15}"
    ...
    echo "$out" >> "outFileName"

done < "$fileName"

问题是,C 处理一个 400MB 的文件大约需要半分钟,而 shell 脚本需要 15 分钟。

我不知道是我做错了什么还是没有在 shell 脚本中使用正确的运算符。

编辑:我不能使用 awk,因为没有模式来处理该行

我尝试评论“echo $out”>>“$outFileName”,但并没有变得更好。我认为问题在于 ${line:106:61} 操作。有什么建议?

感谢您的帮助。

【问题讨论】:

  • 我们可以看看你的shell脚本吗?
  • 你在你的shell脚本中使用awk吗?使用awk 读写文件几乎不需要一分钟。here
  • 如果您在 shell 脚本中逐行处理文件,而且速度要慢 30 倍,这听起来是对的。例如,每次执行 >> 时,都会打开和关闭文件,而在 C 语言中则保持打开状态(顺便说一句,您也可以在 shell 脚本中保持打开状态)。
  • 请发布您的 shell 脚本和有关您正在运行它的 shell 的信息。
  • 能看到C程序的相关部分吗?

标签: c performance bash shell


【解决方案1】:

按照捐赠者和迪特里希的建议,我对 AWK 语言做了一些研究,再次,正如他们所说,这是完全成功的。这是 AWK 程序的一个小例子:

#!/bin/awk -f
{
    option=substr($0, 5, 9);

    if (option=="SOMETHING"){
        type=substr($0, 80, 1)
        if (type=="A"){
            type="01";
        }else if (type=="B"){
            type="02";
        }else if (type=="C"){
            type="03";
        }

        print substr($0, 7, 3) substr($0, 49, 8) substr($0, 86, 8) type\
        substr($0, 568, 30) >> ARGV[2]

    }
}

它就像一个魅力。处理一个 500mb 的文件只需要 1 分钟

【讨论】:

    【解决方案2】:

    C 程序有什么问题?它坏了吗?维护太难?太不灵活?您更像是壳牌专家而不是 C 专家?

    如果没坏,就不要修。

    看看 Perl 也可能是一种选择。比 C 更容易修改,而且 I/O 速度仍然很快;在 Perl 中创建无用的分支比在 shell 中要困难得多。

    如果您确切地告诉我们 C 程序的作用,也许在 Unix 工具箱中有一个简单且速度超快的解决方案,其中包含 sed、grep、awk 或其他 gizmo。换句话说,告诉我们您真正想要实现的目标,不要要求我们解决您在追求您认为朝着实际目标迈出的一步时遇到的一些随机问题。

    好的,你的 shell 脚本的一个问题是 openecho "$out" &gt;&gt; "outFileName" 中的重复。改用这个:

    while read line; do
        echo "${line:10:16}.${line:45:2}${line:106:61}${line:189:3}${line:215:15}..." 
    done < "$fileName" > "$outFileName"
    

    作为替代方案,只需使用cut 实用程序(但请注意,它不会在第一部分之后插入点):

    cut -c 10-26,45-46,106-166 "$fileName" > "$outFileName"
    

    你明白了吗?

    【讨论】:

    • 它没有损坏,但很难找到 C 专家来维护或扩展该过程。
    • 我明白了,但它需要同样的时间,也许少了 1 分钟。我尝试评论 tue "echo "$out" >> "$outFileName" 但并没有变得更好。我认为问题在于 ${line:106:61} 操作。有什么建议吗?
    • 您尝试过cut 解决方案吗?这需要多长时间?如果你不能没有它,可以使用以下 sed 修改 cut 的结果以插入点。
    【解决方案3】:

    根据您的描述,我怀疑您在 shell 脚本中生成了新进程。如果是这样的话,那么这就是你的时间的去向。 fork/exec 一个新进程需要大量操作系统资源。

    【讨论】:

      猜你喜欢
      • 2010-11-09
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 2016-06-15
      • 2013-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多