Haskellのreadは[Char]を任意の型の値にパースするから 普通に考えれば普通の関数ではなさそう。型クラスで 云々すればちゃんとした関数として定義できるそうだけど、 例えばIntにするとわかっていれば、自前でパースするのに 比べれば遅いだろう。しかしどうせreadする時には一緒に 型も指定するのだから、あんまり構造的でない型、Intみたいな 基本的な型についてはそれ用のreadがあってもいい。実際 あるのかな。
とりあえず、ただのreadで"123"を123に変換することを10万回 やってみる。私のPCはあんまり良いものでないので、この位の 回数で時間を測るのがちょうどよかった。
コンパイルして実行するが、最適化はわざとしてない。
-- read_times.hs
a = "123"
n = 100000
main = print reads
where
reads :: [Int]
reads = map (\x -> read a) [0 .. n]
$ time ./test > /dev/null
real 0m1.121s
user 0m1.056s
sys 0m0.024s
これで(n+1)回、aをreadしてることになるだろう。 具体的に出力してみないと評価してくれないので、 実行の際には/dev/nullに捨ててる。出力自体の 時間なんて測りたくないので。
次は自前のパース。先頭から一文字ずつdigitToIntしてる。 これのために最初にimportがある。
-- read_times2.hs
import Data.Char
a = "123"
n = 100000
main = print reads
where
reads :: [Int]
reads = map (\x -> read_int a) [0 .. n]
read_int str = read_int' str 0
where
read_int' [] ac = ac
read_int' (s:ss) ac = read_int' ss (ac*10+digitToInt s)
$ time ./test > /dev/null
real 0m0.109s
user 0m0.072s
sys 0m0.004s
3行くらい長くなったけど、時間は1/10になった。すごい
readのtoInt専用の何かがあるかちょっと調べてみたけど 見つからなかった。あんまり探す気なかったけど。