繰り返し文字生成の実行時間

2024/08/31 19:08 OS別::Linuxその他::シェル
bash で Separator のような、任意の文字を繰り返し出力する方法を探して、見つけたこちら。
https://genzouw.com/entry/2020/10/29/211143/2094/

選択肢が割とあって「お、おう……」となったので「実行速度」で選ぶことにした記事。
シェルスクリプトなので、普段は実行時間なんて気にしないのだけど。

ここで結論を先に書いておくと、ビルトインコマンドである for 文(for *1; do echo -n '='; done)を利用するのが最強のようです。
次点で、print (printf "=%0.s" 0..9)でした。

*1 : i=0; i<10; i++

テスト環境

テスト環境は、以下のような状況です。
$ uname -moi
armv7l unknown GNU/Linux
$
$ bash -version | head -n 1
GNU bash, バージョン 5.1.4(1)-release (arm-unknown-linux-gnueabihf)
$
$ . /etc/os-release
$ echo ${PRETTY_NAME}
Raspbian GNU/Linux 11 (bullseye)

テスト方法

スクリプトにしておいて、シンプルに time で計測します。

作成したスクリプトおよび内容は、以下の通りです。
$ ls -1
test-A.sh
test-B.sh
test-C.sh
test-D.sh
test-E.sh
test-F.sh
test-G.sh
work.sh
$
$ for i in *.sh
do
  echo "### ${i}"
  echo "----------------------------------------------------"
  cat ${i}
  echo "----------------------------------------------------"
  echo ""
done
### test-A.sh
----------------------------------------------------
#!/bin/bash
printf "=%0.s" {0..9}
----------------------------------------------------

### test-B.sh
----------------------------------------------------
#!/bin/bash
yes = | head -n 10 | tr -d '\n'
----------------------------------------------------

### test-C.sh
----------------------------------------------------
#!/bin/bash
seq -s '=' 0 10 | tr -d '[0-9]'
----------------------------------------------------

### test-D.sh
----------------------------------------------------
#!/bin/bash
seq -s '=' 0 10 | sed "s/[0-9]//g"
----------------------------------------------------

### test-E.sh
----------------------------------------------------
#!/bin/bash
for ((i=0; i<10; i++)); do echo -n '='; done
----------------------------------------------------

### test-F.sh
----------------------------------------------------
#!/bin/bash
seq 10 | xargs -i echo -n =
----------------------------------------------------

### test-G.sh
----------------------------------------------------
#!/bin/bash
seq 10 | xargs -i printf "="
----------------------------------------------------

### work.sh
----------------------------------------------------
#!/bin/bash

fnChecker() {
  echo "### ${1}"
  time ./${1}
}

fnChecker test-A.sh
fnChecker test-B.sh
fnChecker test-C.sh
fnChecker test-D.sh
fnChecker test-E.sh
fnChecker test-F.sh
fnChecker test-G.sh
----------------------------------------------------

$

計測

傾向が見えればよいと考えたため、とりあえず1回実行したところが、以下の数値です。
$ ./work.sh
### test-A.sh
==========
real    0m0.016s
user    0m0.013s
sys     0m0.003s
### test-B.sh
==========
real    0m0.028s
user    0m0.020s
sys     0m0.030s
### test-C.sh
==========

real    0m0.023s
user    0m0.024s
sys     0m0.007s
### test-D.sh
==========

real    0m0.028s
user    0m0.009s
sys     0m0.028s
### test-E.sh
==========
real    0m0.014s
user    0m0.001s
sys     0m0.013s
### test-F.sh
==========
real    0m0.082s
user    0m0.026s
sys     0m0.067s
### test-G.sh
==========
real    0m0.080s
user    0m0.036s
sys     0m0.051s
$

結論

for コマンドを使います。

感想

printf コマンド(test-A.sh)もなかなか良い数字なんだけど、ビルトインコマンドの for によるループ(test-E.sh)が強いですね。

その他、普通は bash の予約語なので利用されない time コマンドを使ってみての計測なんかもしてみましたが、メモリ使用率なんかは変化が少ないようです。

wait

time コマンドで計測できる wait の内容は、次の通り(man bash の引用)。
wait の回数、つまりそのプログラムが自発的にコンテキストスイッチされた回数。
例えば、I/O 操作の完了を待っている間などが該当する。
$ type time
time はシェルの予約語です
$
$ which time
/usr/bin/time
$
$ for i in test-*.sh
> do
>    /usr/bin/time -f "\nwait: %w" ./${i}
> done
==========
wait: 1
==========
wait: 8
==========

wait: 7
==========

wait: 5
==========
wait: 1
==========
wait: 31
==========
wait: 36
$
計測した結果は上記の通りですが、printf と for でのループ、待ちなんてほとんど発生してませんね。

その他

あと、こんな感じで他にもいろいろ計測できたりします。

これは、メモリ(プロセス生存中のそのプロセスの resident set size の最大値)。
$ for i in test-*.sh
do
   echo "### ${i}"
   /usr/bin/time -f "\n Memory: %MKB" ./${i}
done
### test-A.sh
==========
 Memory: 2752KB
### test-B.sh
==========
 Memory: 2820KB
### test-C.sh
==========

 Memory: 2820KB
### test-D.sh
==========

 Memory: 2816KB
### test-E.sh
==========
 Memory: 2692KB
### test-F.sh
==========
 Memory: 2868KB
### test-G.sh
==========
 Memory: 2868KB
$
うん。だいたい 3MB 程度ですね。

メジャーページフォルトの回数

外部コマンドでは、メジャーページフォルトの回数を計測も出来たりします。
$ for i in test-*.sh
do
   echo "### ${i}"
   /usr/bin/time -f "\n Page: %F" ./${i}
done
有意な差がないので結果は載せないですが、test-C.sh (seq -s '=' 0 10 | tr -d '[0-9]') はちょこちょこページフォルトが発生している模様。
他のも、合ったりなかったり。
$ for i in test-*.sh
do
   echo "### ${i}"
   /usr/bin/time -f "\n Memory: %MKB" ./${i}
done

pwsh update

2024/03/27 06:43 OS別::Windowsその他::シェル
Windows PowerShell を Windows Terminal でアップデートする手順を記載します。

環境

この手順は、以下の Windows バージョンで確認しています。
OS Version
OS Version

バージョンアップ

Windows Terminal の起動

筆者の環境では PowerShell を起動すると、Windows Terminal が開きます。
Windows Terminal
Windows Terminal

バージョン確認

PowerShell のバージョンを確認しておきます。
PS C:\Users\test> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      22621  2506


PS C:\Users\test>

インストール

次のコマンドで、Microsoft Store から PowerShell の最新版を確認し、インストールします。

なお、winget コマンドは Microsoft の パッケージ管理ツール になります。
PS> winget search Microsoft.PowerShell
PS> winget install --id Microsoft.Powershell --source winget
PS> winget install --id Microsoft.Powershell.Preview --source winget
もしユーザアカウント制御 (UAC) が表示された場合は、「はい」を選択してください。
PowerShell 7.4 install
PowerShell 7.4 をインストール中の画面です。
PowerShell 7.4 install
PowerShell 7.4 install
PowerShell 7.5 install
PowerShell 7.5 Preview をインストール中の画面です。
PowerShell 7.5 install
PowerShell 7.5 install

インストール完了画面

どちらもインストールを完了すると、下の画面のようになります。
PowerShell インストール完了
PowerShell インストール完了

Windows Terminal 設定

インストールしただけでは Windows Terminal に反映されないようです。
Windows Terminal を再起動するか、新しいプロファイルとして設定します。

なお、インストールした PowerShell は、別なディレクトリに格納されています。
C:\Program Files\PowerShell\7\pwsh.exe
新しいプロファイルとして設定する場合は、参考にしてみてください。
そのまま設定すると、自身のプロファイルを設定・保存した際に新しい PowerShell が定義されたので、Windows Terminal を再起動すれば設定されているのかもしれません(確認不能状態になってしまいました)

Windows Terminal 設定を開く

必要であれば Windows Terminal 設定画面を開きます。
Windows Terminal 設定
Windows Terminal 設定

新しいプロファイルを開く

「新しいプロファイルを開く」を選択します。
新しいプロファイルを追加します
新しいプロファイルを追加します

新しい空のプロファイルを開く

「新しい空のプロファイルを開く」を選択します。
新しい空のプロファイル
新しい空のプロファイル

プロファイルを設定する

必要事項を入力して、「保存」を選択します。
プロファイル設定
プロファイル設定

プロファイル設定後

筆者の環境では、設定してプロファイルを保存すると、自動的に 7.4 および 7.5 が適切に設定されました。
せっかく設定しましたが、自分で設定したプロファイルは「プロファイルの削除」を選択して削除しました。
PowerShell 7.4 プロファイル設定後
PowerShell 7.4 プロファイル設定後
PowerShell 7.4 プロファイル設定後
PowerShell 7.5 プロファイル設定後
PowerShell 7.5 プロファイル設定後
PowerShell 7.5 プロファイル設定後

PowerShell 7.4

新しく開く

新しく開く
新しく開く

バージョン確認

PowerShell 7.4 バージョン確認
PowerShell 7.4 バージョン確認

参考