Haskellで外部実行ファイルの実行時間を調べる。つづき

Haskellで外部実行ファイルの実行時間を調べる。 - 妄想宝箱の続き。


ふつうのHaskell届いたぜ。
ということで、前のやつのバージョンアップを。


やることは

の三つ。

2個以上の引数も対応する

前のコードの一部

main = do
    args <- getArgs
    wait $ head args


以前はhead関数を使ってたら、配列の最初しか取得できなかったけど、
「ふつうのHaskell」にunwordというStringの配列を結合する便利なのが紹介されてたのでそれを使用。


変更後。

main = do
    args <- getArgs
    wait $ unwords args

かっこよく時間を表示

以前はTimeDiffをそのままshowしてただけだから出力したデータが見にくかった。
で、改善するためにてきとーにshowTimeという関数を作った。

showTime :: TimeDiff -> String
showTime (TimeDiff year month d h m s p) = showNonZero year "year " ++
    showNonZero month "month " ++  showNonZero d "d " ++
    showNonZero h "h " ++ show m ++ "m "++ show s ++ "s " ++
    (show $ div p 1000000000) ++ "ms"

showNonZero :: (Num a) => a -> String -> String
showNonZero 0 _ = ""
showNonZero x unit = show x ++ unit


なんか汚いコードだな・・・。dataの使い方がいまいちよく分からん。
配列の用に(x:xs)のようなパターンマッチ使えるとうまく書けそうだけど、dataにないの?


あと前のコメントでも言われていたが、ピコ秒単位での取得出来てないっぽいのでミリ秒単位に変更。

リファクタリング


…するとこねぇー!
たぶん、>>=とか使えばもっと短くなるかもしれんが、これ以上やるとわかり難くなりそう。


ということで完成品。

--引数に入れた外部ファイルの実行速度を測るぜ!
module Main where
import System
import System.Process
import Time
main = do
    args <- getArgs
    start <- getClockTime
    wait $ unwords args
    end <- getClockTime
    putStrLn $ showTime $ diffClockTimes end start
	
wait :: String -> IO ExitCode
wait = (>>= waitForProcess) . runCommand

showTime :: TimeDiff -> String
showTime (TimeDiff year month d h m s p) = showNonZero year "year " ++
    showNonZero month "month " ++  showNonZero d "d " ++
    showNonZero h "h " ++ show m ++ "m "++ show s ++ "s " ++
    (show $ div p 1000000000) ++ "ms"

showNonZero :: (Num a) => a -> String -> String
showNonZero 0 _ = ""
showNonZero x unit = show x ++ unit


やっぱりshowTimeが長い。

実行

sosu.exeの実行時間を計りたい場合、コマンドプロンプトで以下のコマンドを実行。

>theResult.exe sosu.exe
0m 3s 812ms


きちんと3.812秒と出力された。


もちろん複数の引数も可能

>theResult.exe java -jar sosu.jar
0m 3s 750ms
>

誤差

前の日記でhello.exeの実行時間測れたぜ!やほーう!
て書いてたらこんなコメントが、

内部実装はまったく知らないけどタイマ精度は十分なの?
# 例えばほかに何も起動してない状態でC標準関数のclock()を連続して呼んでみよう
Windowsでピコ秒単位でとるの無理じゃない?


ええ、はい、そのとおりですね。
誤差を測ってみた所、0.016sほどありました。
つまりそれ以下の精度を測るのは無理と。


なので、すぐ終わるようなexeファイルを測定してもあまり意味が無く、
ある程度時間がかかるやつを測定したほうがいい。