普遍的な非bashの「時間」ベンチマークの代替?[閉まっている]


10

異なるシェル間でスクリプトの実行時間を比較するために、一部のSEの回答は、次のようにbash組み込み timeコマンドの使用を提案しています。

time bash -c 'foo.sh'
time dash -c 'foo.sh'

... など、すべてのシェルをテストします。このようなベンチマークでは、各シェルがそれ自体をロードして初期化するのにかかる時間を排除できません。例えば、上記のコマンドの両方が上に格納されたと仮定初期フロッピーディスクの読み出し速度と遅いデバイス、(124キロバイト/秒)、 dash〜150K実行)についてロードする7Xより速くbash〜1M)、シェル読み込み時間はtime数値を歪めます-これらのシェルの事前読み込み時間は、シェルが読み込まれたfoo.sh各シェルの下の実行時間の測定には関係ありません。

各シェルから実行できるスクリプトタイミング用に実行するのに最適なポータブルで一般的なユーティリティは何ですか?したがって、上記のコードは次のようになります。

bash -c 'general_timer_util foo.sh'
dash -c 'general_timer_util foo.sh'

注意:移植性や汎用性がないため、シェル組み込み timeコマンドはありません。


さらに、utilがシェルの内部コマンドとパイプラインにかかる時間をベンチマークでき、ユーザーが最初にそれらをスクリプトにラップする必要がない場合はさらに良いでしょう。このような人工的な構文は役に立ちます:

general_timer_util "while read x ; do echo x ; done < foo"

一部のシェルtimeはこれを管理できます。たとえばbash -c "time while false ; do : ; done"動作します。システムで何が機能するか(そして機能しないか)を確認するには、次のことを試してください。

tail +2 /etc/shells | 
while read s ; do 
    echo $s ; $s -c "time while false ; do : ; done" ; echo ----
done

6
ただ使う/usr/bin/time
クサラナンダ

1
私はどのように理解していない任意の非組み込みはおそらく「負荷に各シェルにかかる時間を排除し、自分自身を初期化」と「ポータブルおよび一般的な」ながらスタンドアロンスクリプトが実行される可能性があり、両方。
Michael Homer

1
それは質問に対する答えではありません。それは、あなたが何を望んでいるかを明確にするためのプロンプトです。
Michael Homer

1
私は最善の試みを投稿しましたが、実際に何を達成しようとしているのかについての質問はまだ具体化されていないと思います。
Michael Homer

2
「ポータブルまたは一般」とはどういう意味ですか?シェルのビルトインは、外部コマンドと同じくらい移植性があり(多くのシステムで動作します)、より一般的です(ファイルの実行以外の時間を計測できるため、より多くの状況で動作します)。どのような問題を解決しようとしていますか?
Gilles 'SO-邪悪なことをやめなさい'

回答:


10

timeはPOSIX指定されいることに注意してください。また、AFAICTがPOSIXで言及されている唯一のオプション(-p)は、さまざまなシェルで正しくサポートされています。

$ bash -c 'time -p echo'

real 0.00
user 0.00
sys 0.00
$ dash -c 'time -p echo'

real 0.01
user 0.00
sys 0.00
$ busybox sh -c 'time -p echo'

real 0.00
user 0.00
sys 0.00
$ ksh -c 'time -p echo'       

real 0.00
user 0.00
sys 0.00

1
問題は、タイミングを比較できるようにするには、の同じ実装で結果のタイミングをとる必要があることですtime。これは、スプリンターが自分の時間を1つの時計で同時に測定するのではなく、100mで個別に測定できるようにすることと同等です。これは明らかにつらいことですが、それでも...
Kusalananda

@Kusalananda OP timeは移植性がないと思ったのが問題だと思った。持ち運びできるようです。(ただし、比較可能性についてのあなたの意見に同意します)
muru

@muru、私のシステムでdash -c 'time -p while false ; do : ; done'「time:cannot run while:No such file or directory <cr> Command exited with non-zero status 127」エラー返されます。
agc

1
@agc POSIXはまた、次のように述べています。標準ユーティリティだけでなく、シェルスクリプト」(セクション
RATIONALEを


7

高解像度タイマーをサポートするGNU dateコマンドを使用します

START=$(date +%s.%N)
# do something #######################

"$@" &> /dev/null

#######################################
END=$(date +%s.%N)
DIFF=$( echo "scale=3; (${END} - ${START})*1000/1" | bc )
echo "${DIFF}"

次に、次のようにスクリプトを呼び出します。

/usr/local/bin/timing dig +short unix.stackexchange.com
141.835

出力単位はミリ秒です。


1
時間(エポック時間)が途中で変化しないと仮定します。それが問題を引き起こすが実際に言及する価値があるケースを実際に考えることはできません。
2017年

1
これにはdate特にGNUが必要であることを追加する必要があります。
クサラナンダ

@phk説明してください。
Rabin

1
@Rabin NTPクライアントが問題を起こし、クロックを更新して場所STARTEND設定の間で変更するとします。これは明らかに結果に影響します。あなたがそれをどれほど正確に必要とするか、それがあなたのケースで重要かどうかはわかりませんが、私が言ったように、覚えておくべきことはあります。(楽しい話:予想外のマイナスの結果につながるソフトウェアを知っています–スループットの計算に使用されたため、いくつかの問題が発生しました。)
phk

1
また、一部のNTPクライアントは、システム時刻を「ジャンプ」させるのではなく、クロックを遅くしたり、速くしたりしませんか?そのようなNTPクライアントがあり、昨日の夕方にいくつかのタイミングを行った場合、それらはおそらく、うるう秒を「予測」しているNTPクライアントによって歪められています。(または、その場合、システムクロックは単に61まで実行されますか?)
JörgW Mittag

6

このtimeユーティリティは通常、シェルに組み込まれているため、「中立」タイマーとしては使えません。

ただし、このユーティリティは通常、外部ユーティリティとしても利用でき/usr/bin/timeます。これは、提案するタイミング実験を実行するために使用できます。

$ bash -c '/usr/bin/time foo.sh'

これはどのようにして「各シェルが自身をロードして初期化するのにかかる時間を排除する」のですか
Michael Homer

1
場合はfoo.sh、実行可能であるとシェバングを持っている、これは常に同じシェルでそれを実行し、そしてそれは、そのシェルの起動時間をカウントし、これはOPが望んでいるものではありません。foo.shこれらのいずれかが欠落している場合、これはまったく機能しません。
ケビン

@ケビン非常に本当です。「シェル組み込みなし」のみtimeを考慮したようです。シェルの起動時間は個別に測定する必要がある場合があります。
クサラナンダ

1
timeコマンドが組み込まれているシェルは知りません。ただし、を含む多くのシェルにbashは、timeパイプラインの時間を計測するために使用できるキーワードがあります。そのキーワードを無効にしてtime(ファイルシステムで)コマンドを使用するには、のように引用符で囲みます"time" foo.sh。参照してくださいunix.stackexchange.com/search?q=user%3A22565+time+keyword
ステファンChazelas

6

以下がその解決策です。

  1. 各シェルが自分自身をロードして初期化するのにかかる時間をなくす

  2. 各シェルから実行できます

  3. 用途

    time移植可能なコマンドや一般的なコマンドはないため、シェルの組み込みコマンドはありません。

  4. すべてのPOSIX互換シェルで動作します。
  5. Cコンパイラを備えたすべてのPOSIX互換およびXSI準拠のシステム、またはC実行可能ファイルを事前にコンパイルできるシステムで動作します。
  6. すべてのシェルで同じタイミング実装を使用します。

2つの部分があります:をラップする短いCプログラムgettimeofday(非推奨ですが、それよりも移植性が高いclock_gettime)と、そのプログラムを使用して、スクリプトのソースの両側を読み取るマイクロ秒精度の時計を取得する短いシェルスクリプトです。Cプログラムは、タイムスタンプの1秒未満の精度を取得するための唯一のポータブルでオーバーヘッドの少ない方法です。

ここにCプログラムがありepoch.cます:

#include <sys/time.h>
#include <stdio.h>
int main(int argc, char **argv) {
    struct timeval time;
    gettimeofday(&time, NULL);
    printf("%li.%06i", time.tv_sec, time.tv_usec);
}

そしてシェルスクリプトtimer

#!/bin/echo Run this in the shell you want to test

START=$(./epoch)
. "$1"
END=$(./epoch)
echo "$END - $START" | bc

これは標準のシェルコマンド言語でありbc、POSIX互換シェルの下でスクリプトとして機能するはずです。

これは次のように使用できます。

$ bash timer ./test.sh
.002052
$ dash timer ./test.sh
.000895
$ zsh timer ./test.sh
.000662

システム時間やユーザー時間は測定されず、非単調な壁時計の経過時間のみが測定されます。スクリプトの実行中にシステムクロックが変更されると、不正な結果が生じます。システムに負荷がかかっている場合、結果は信頼できなくなります。シェル間でこれ以上移植できるものはないと思います。

変更されたタイマースクリプトevalは、スクリプトの外でコマンドを実行する代わりに使用できます。


ただこれを読んで前に偶然、(約最後の行eval)、私は微調整されたでスクリプトをラビンの答え含まれるようにeval "$@"、それはシェル実行できるので、組み込みコマンドをその場で。
agc

4

複数回使用してソリューションを改訂/proc/uptimeし、dc/ bc/ awkによって大部分での入力のおかげでAGC

#!/bin/sh

read -r before _ < /proc/uptime

sleep 2s # do something...

read -r after _ < /proc/uptime

duration=$(dc -e "${after} ${before} - n")
# Alternative using bc:
#   duration=$(echo "${after} - ${before}" | bc)
# Alternative using awk:
#   duration=$(echo "${after} ${before}" | awk '{print $1 - $2}')

echo "It took $duration seconds."

それは明らかに/proc/uptime存在し、特定の形式を持っていると仮定します。


3
これはシェル間での移植を可能にしますが、Unix実装間での移植はできません/proc。これが心配かどうかは分からない。
クサラナンダ

1
強調するために、このQはフロッピーディスクの速度以下を示唆しています。この場合、読み込みのオーバーヘッドawkが大きくなる可能性があります。たぶんb=$(cat /proc/uptime)前、a=$(cat /proc/uptime)後、そして$ a$ bを解析して減算します。
agc

@agc良い入力、ありがとう、それに応じていくつかの代替ソリューションを追加しました。
phk 2017

1
前にそれを考えるが、場合しませんでした組み込みコマンドが好きreadよりも優れているcat、これだろうクリーナー(と少し速い): read before dummyvar < /proc/uptime ;sleep 2s;read after dummyvar < /proc/uptime; duration=$(dc -e "${after} ${before} - n");echo "It took $duration seconds."
AGC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.