Skip to content

Instantly share code, notes, and snippets.

@whilo
Created April 5, 2018 00:16
Show Gist options
  • Save whilo/a394f5e63ff8dbce54f1816531cb45a1 to your computer and use it in GitHub Desktop.
Save whilo/a394f5e63ff8dbce54f1816531cb45a1 to your computer and use it in GitHub Desktop.
Clojure STM example
(def accounts
(into {} (for [i (range 1000001)]
[i (ref 1000)])))
(time
(let [fs (dotimes [offset 10]
(future
(doseq [i (shuffle (range (* offset 100000)
(* (inc offset) 100000)))]
(dosync
(alter (accounts i) + 100)
(alter (accounts (inc i)) - 100)))))]
(doseq [f fs]
@f)))
@vizanto
Copy link

vizanto commented Apr 10, 2018

Lazily create accounts like this:

(def lazy-accounts (atom {}))

(defn create-account-ref [accounts account-id]
  (if (accounts account-id) accounts
   #_else (assoc accounts account-id (ref 1000))))

(defn account-ref [account-id]
  (locking lazy-accounts ; otherwise n threads could create n-1 refs that are immediately trashed (wasting CPU on expensive query to put into ref)
    ((swap! lazy-accounts create-account-ref account-id) account-id)))

; Time it
(time
 (let [fs (for [offset (range 10)]
            (future
              (doseq [i (shuffle (range (* offset 100000)
                                        (* (inc offset) 100000)))]
                (dosync
                 (alter (account-ref i) + 100)
                 (alter (account-ref (inc i)) - 100)))))]
   (doseq [f fs]
     @f)))

"Elapsed time: 1614.612589 msecs"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment