id:eel3:20141011:1412954857 の続き。いや、CygwinではなくLinuxで計測してみただけですがな。
Cygwinは少々特殊な環境だし、そもそもWindows上ではアンチウイルスソフトその他の影響でプロセス生成コストが高くなる。Unix環境でのプロセス生成コストとは大違いだ。
という訳で、前回とは別のマシン(Celeron 847にメモリ4GBの自作PC)のUbuntu 12.04にて計測してみた。
$ uname -a Linux fabrico 3.2.0-68-generic-pae #102-Ubuntu SMP Tue Aug 12 22:23:54 UTC 2014 i686 i686 i386 GNU/Linux $ seq --version seq (GNU coreutils) 8.13 Copyright (C) 2011 Free Software Foundation, Inc. ライセンス GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. 作者 Ulrich Drepper。 $ sed --version GNU sed バージョン 4.2.1 Copyright (C) 2009 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. 訳注: 非常に重要な文章のため、原文を残しています。 -- 参考訳 これはフリー・ソフトウェアです。複製の条件に関しては、ソースをご覧くださ い。保証は一切ありません。営利目的や法で定められた範囲での特定目的のため の適合性もありません。 GNU sed ホームページ: <http://www.gnu.org/software/sed/>. GNU ソフトウェアを使用する際の一般的なヘルプ: <http://www.gnu.org/gethelp/>. 電子メールによるバグ報告の宛先: <bug-gnu-utils@gnu.org> 報告の際、“Subject:” フィールドのどこかに “sed” を入れてください。 翻訳に関するバグは<translation-team-ja@lists.sourceforge.net>に報告してください。 $ printf --version bash: printf: --: 無効なオプションです printf: 使用法: printf [-v var] format [arguments] $ bash --version GNU bash, バージョン 4.2.25(1)-release (i686-pc-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. $ time seq 1 10000000 | sed 's/^.*$/echo & !/' >/dev/null real 0m20.650s user 0m34.554s sys 0m0.184s $ time seq 1 10000000 | xargs printf 'echo %s !\n' >/dev/null real 0m18.112s user 0m27.122s sys 0m4.308s $ time seq 1 10000000 | xargs printf 'echo %d !\n' >/dev/null real 0m18.667s user 0m29.234s sys 0m4.420s
Cygwin上よりも遥かに高速ですね! ハードウェア・スペック的には今回の環境の方が圧倒的に劣るのだが。あと、Cygwinでの計測結果とは異なり、printf(1)を使用したほうが2秒ぐらい速い。
awk(1)ではどうだろうか?
$ awk --version GNU Awk 3.1.8 Copyright (C) 1989, 1991-2010 Free Software Foundation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. $ time seq 1 10000000 | awk '{ print "echo " $0 " !" }' >/dev/null real 0m14.850s user 0m25.714s sys 0m0.168s $ time seq 1 10000000 | awk '{ printf("echo %s !\n", $0) }' >/dev/null real 0m14.765s user 0m26.606s sys 0m0.156s $ time seq 1 10000000 | awk '{ printf("echo %d !\n", $0) }' >/dev/null real 0m34.866s user 0m49.091s sys 0m0.324s
意外にも、データを文字列として扱っている限りは、実時間もCPU時間もsed(1)より少ない。Cygwinの時と同様に、printfで%dを使用した場合は遅くなるようだ。文字列から数値へ、数値から文字列へと二重に変換が発生するためだろう。
Ubuntu 12.04では、gawk(1)をインストールしていない場合のawk(1)はmawk(1)だ。どう違うだろうか?
$ mawk -W version mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan compiled limits: max NF 32767 sprintf buffer 1020 $ time seq 1 10000000 | mawk '{ print "echo " $0 " !" }' >/dev/null real 0m14.631s user 0m19.089s sys 0m0.284s $ time seq 1 10000000 | mawk '{ printf("echo %s !\n", $0) }' >/dev/null real 0m14.734s user 0m21.501s sys 0m0.228s $ time seq 1 10000000 | mawk '{ printf("echo %d !\n", $0) }' >/dev/null real 0m14.770s user 0m24.254s sys 0m0.256s
gawk(1)とmawk(1)のどちらも、今回の処理内容においては、データを文字列として扱っている限り実時間は同程度で、CPU時間はわずかにmawk(1)の方が小さかった。しかし興味深いことに、printfでデータを文字列ではなく数値として扱った際に、mawk(1)では処理時間が全く遅くならなかった。
おまけとして、今回もOpen usp Tukubaiのmojihame(1)で計測をば。
$ python --version Python 2.7.3 $ mojihame Usage : mojihame <template> <data> (通常) : mojihame -l <label> <template> <data> (行単位) : mojihame -h <label> <template> <data> (階層データ) Option : -d[c] Version : Fri Oct 21 11:26:06 JST 2011 Open usp Tukubai (LINUX+FREEBSD/PYTHON2.4/UTF-8) $ echo 'echo %1 !' >template.txt $ time seq 1 10000000 | mojihame -l template.txt >/dev/null real 6m59.530s user 7m11.759s sys 0m0.328s
Cygwinよりも遅くなってしまった! 何となく、露骨にハードウェア性能の差が出た結果であるようにも思える。usp Tukubaiのmojihame(1)での実力値を見てみたいなあ。
では最後に、whileループで締めくくろう。このUbuntuにはbash以外にdashとbusyboxがインストールされているので、それぞれの比較もしてみた。
$ /bin/bash $ time seq 1 10000000 | while read i; do echo echo $i '!'; done >/dev/null real 6m8.858s user 5m12.944s sys 1m10.476s $ exit $ /bin/dash $ time seq 1 10000000 | while read i; do echo echo $i '!'; done >/dev/null 14.79user 0.28system 1:50.95elapsed 13%CPU (0avgtext+0avgdata 2592maxresident)k 0inputs+0outputs (0major+207minor)pagefaults 0swaps $ exit $ /bin/busybox sh BusyBox v1.18.5 (Ubuntu 1:1.18.5-1ubuntu4.1) built-in shell (ash) Enter 'help' for a list of built-in commands. ~ $ time seq 1 10000000 | while read i; do echo echo $i '!'; done >/dev/null real 2m 35.94s user 0m 14.16s sys 0m 0.25s ~ $ exit
Cygwinではmojihame(1)よりもbashのwhileループの方が遅かったが、Ubuntuでは逆転している。とはいえ、やはり遅いことには変わりがない。この結果も、露骨にハードウェア性能の差が出たためではないかと感じる。
dashやbusyboxのshのwhileループは、bashよりも高速だった。なるほど、よく「bashは遅い」という記述を目にするが、純粋に内部コマンド(ビルトインコマンド)のみで勝負した場合、bashは他のUnixシェルよりも遅いのだろう*1。
しかし、いくらdashやbusyboxのshのwhileループが高速だといえども、sed(1)などのテキストフィルタを使う方法にはるかに及ばないようだ。