# atomの配列と配列のatom

Clojureは基本的にmutableなものを許さない設計になっているので、do-syncなどのトランザクションの中でrefを変更するコストは結構高い(はず)。ドランザクションではないけど、atomの場合でちょっと実験してみる。

atomの配列と配列のatomを用意。要素をランダムに置き換えていくような実験の設定。

```(def x (atom '[1 2 3]))
(def y [(atom 1) (atom 2) (atom 3)])
(def N 100000)

(println "x")
(dotimes [_ 5]
(let [rand-seq (doall (vec (map (fn [_] (rand-int 3)) (range N))))]
(time (dotimes [i N]
(let [n (nth rand-seq i)]
(swap! x assoc n n))))))

(println "y")
(dotimes [_ 5]
(let [rand-seq (doall (vec (map (fn [_] (rand-int 3)) (range N))))]
(time (dotimes [i N]
(let [n (nth rand-seq i)]
(reset! (y n) n))))))
```

```x
"Elapsed time: 261.819 msecs"
"Elapsed time: 251.127 msecs"
"Elapsed time: 242.16 msecs"
"Elapsed time: 240.869 msecs"
"Elapsed time: 256.606 msecs"
y
"Elapsed time: 108.052 msecs"
"Elapsed time: 119.755 msecs"
"Elapsed time: 79.847 msecs"
"Elapsed time: 82.929 msecs"
"Elapsed time: 79.497 msecs"
```

## 違う設定で実験

```(def x (atom (vec (range 10000))))
(def y (vec (for [i (range 10000)] (atom i))))

(def N 100000)

(println "x")
(dotimes [_ 5]
(let [rand-seq (doall (vec (map (fn [_] (rand-int 10000)) (range N))))]
(time (dotimes [i N]
(let [n (nth rand-seq i)]
(swap! x assoc n n))))))

(println "y")
(dotimes [_ 5]
(let [rand-seq (doall (vec (map (fn [_] (rand-int 10000)) (range N))))]
(time (dotimes [i N]
(let [n (nth rand-seq i)]
(reset! (y n) n))))))
```

やはり配列のatomのほうが遅くなっている度合いが大きいた思ったほどでもなかったような気がする。

```x
"Elapsed time: 780.831 msecs"
"Elapsed time: 701.475 msecs"
"Elapsed time: 695.271 msecs"
"Elapsed time: 651.421 msecs"
"Elapsed time: 646.095 msecs"
y
"Elapsed time: 187.253 msecs"
"Elapsed time: 201.147 msecs"
"Elapsed time: 151.437 msecs"
"Elapsed time: 126.56 msecs"
"Elapsed time: 126.16 msecs"
```

プログラミングClojure