2010年9月23日木曜日

bashによる文字列置換が極端に非効率

bashには、文字列置換を行う機能が用意されており、便利に利用させてもらっています。しかし、これが非常に効率が悪いことがあることを知りました。サンプルプログラムは、次の通りです。
VAR の中の pattern を削除する ${VAR//patern} という書き方が遅い。
#!/bin/bash
# str_replace_perf.bash

#
# prepare 1000 strings of 6 digits
#
TEST_LIST=`seq 100100 100 200000`
echo $TEST_LIST | wc

#
# delete "150000"
#
T0=$SECONDS
A=${TEST_LIST//150000}
T1=$SECONDS
B=`echo $TEST_LIST | sed s/150000//g`
T2=$SECONDS

#
# results
#
echo T1-T0=$((T1-T0))
echo T2-T1=$((T2-T1))

# verify
echo $A | md5sum
echo $B | md5sum
このサンプルスクリプトでは、sed と速さを比較しています。
T1-T0 が bash で処理した場合の経過時間。T2-T1 が sed で同様の処理をした場合の経過時間。わたしのマシンでの実行結果は次の通りです。
[root@fedora14 ~]# cat /etc/redhat-release 
Fedora release 14 (Branched)
[root@fedora14 ~]# uname -r
2.6.35-0.57.rc6.git1.fc14.x86_64
[root@fedora14 ~]# bash --version
GNU bash, version 4.1.7(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[root@fedora14 ~]# ./str_replace_perf.bash 
      1    1000    7000
T1-T0=10
T2-T1=0
de028ddb26bdd0b5aa062b1b8e753665  -
de028ddb26bdd0b5aa062b1b8e753665  -
上はサンプルですが、実際にこのボトルネックにハマって、修正が必要になった物件がありました。
Google で似たような話しが無いかはしばらく探したものの、見つかりませんでしたので、なんとか将来改善されることを期待して、bug-bash@gnu.orgへ連絡しました。

2010-09-25追記
早速、メンテナーの方から返事をもらいました。感謝。
多バイト文字サポートに起因するが、次のバージョン 4.2 に、修正を取り込む予定になっているとのことで、修正作業も既に終えているそうです。
なお、上記(多バイト文字サポートに起因)をヒントに、サンプルスクリプトを実行する前に、LANG=C を設定したところ、同じマシンでのスクリプト実行結果が T1-T0=1 に短縮されることを確認しました。
[root@fedora14 ~]# echo $LANG
ja_JP.UTF-8
[root@fedora14 ~]# ./str_replace_perf.bash 
      1    1000    7000
T1-T0=9
T2-T1=0
de028ddb26bdd0b5aa062b1b8e753665  -
de028ddb26bdd0b5aa062b1b8e753665  -
[root@fedora14 ~]# LANG=C
[root@fedora14 ~]# ./str_replace_perf.bash 
      1    1000    7000
T1-T0=1
T2-T1=0
de028ddb26bdd0b5aa062b1b8e753665  -
de028ddb26bdd0b5aa062b1b8e753665  -

2011-03-03追記
少し遅れましたが、先月 bash-4.2 がリリース済みであることを知り、さっそく試してみたところ、劇的に速くなっていました。メンテナー様、ありがとうございます。
なお、以前とは別のマシンで確認を行っています。
[root@fedora14 ~]# uname -a
Linux fedora14 2.6.35.10-74.fc14.x86_64 #1 SMP Thu Dec 23 16:04:50 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux
[root@fedora14 ~]# echo $LANG
ja_JP.UTF-8
[root@fedora14 ~]# rpm -q bash
bash-4.1.7-3.fc14.x86_64
[root@fedora14 ~]# time ./str_replace_perf.bash 
      1    1000    7000
T1-T0=3
T2-T1=0
de028ddb26bdd0b5aa062b1b8e753665  -
de028ddb26bdd0b5aa062b1b8e753665  -

real    0m3.839s
user    0m3.799s
sys     0m0.020s
[root@fedora14 ~]# rpm -Uvh bash-4.2.0-2.fc15.x86_64.rpm 
警告: bash-4.2.0-2.fc15.x86_64.rpm: ヘッダ V3 RSA/SHA256 Signature, key ID 069c8460: NOKEY
準備中...                ########################################### [100%]
   1:bash                   ########################################### [100%]
[root@fedora14 ~]# time ./str_replace_perf.bash 
      1    1000    7000
T1-T0=0
T2-T1=0
de028ddb26bdd0b5aa062b1b8e753665  -
de028ddb26bdd0b5aa062b1b8e753665  -

real    0m0.028s
user    0m0.014s
sys     0m0.011s

0 件のコメント:

コメントを投稿

人気ブログランキングへ にほんブログ村 IT技術ブログへ