 (ns org.dada.core.test-clojure
     (:use 
      [clojure test]
+     [clojure.contrib math]
      )
     )
 
 (set! *warn-on-reflection* true)
 
+;;--------------------------------------------------------------------------------
 ;; test the speed of various bits of clojure to help ascertain which way DADA should do things
 
 (defmacro millis [times body]
   `(do
+     (System/gc)
      (print (quote ~body))
      (let [start# (System/currentTimeMillis)]
        (do (dotimes [_# ~times] ~body) nil)

;;     (let [^{:tag (type (into-array Object []))} a (into-array Object [0])]
;;       (is (faster 100000000 (Value. 0) (.newInstance c a))))))

;; I'm not going to test this - just make a note of it...
(deftest test-record-vs-pojo
  (let [^Value r (Value. 0)
	^String p ""]
    (faster 100000000 (.v r)(.length p))))

;; this may be needed for where we need to access a field via a function rather than a java accessor... - not much in it...

;; (deftest test-get
;;   (let [^Value v (Value. 0)] (is (faster 1000000000 ((fn [^Value v] (.v v)) v) (:v v)))))

;; doseq nearly twice as fast



;; seems to be true - but so close I can't rely on it not to fail build

;; (deftest assoc-vs-conj
;;   (is (let [n 1000000 i (range n)]
;;         (faster
;;          1
;;          (reduce (fn [r i] (assoc r i i)) {} i)
;;          (reduce (fn [r i] (conj r [i i])) {} i)))))

;; There does not seem to be much difference between record attribute
;; access via dot notation and array access via index. Perhaps rows
;; should be implemented by arrays ?
(if (not (ibm?))
  (deftest record-vs-array-access
    (let [^Value r (Value. 0) ^objects a (into-array Object [0])] (is (faster 1000000000 (.v r) (aget a 0))))))


(defrecord Foo (^int a))
(defrecord Bar (^Integer a))

;; reading an int out of a record is about 2x as slow as reading an
;; Integer - I guess that this is due to autoboxing...
(if (not (ibm?))
  (deftest record-int-vs-integer
    (let [f (Foo. 1) b (Bar. 1)] (is (slower 1000000000 (.a f) (.a b))))))

;; interesting - reading an int out of a record and pssing it into
;; another fn (causing it to be auto-boxed) is still 5-10x faster than
;; just reading an Integer out of a record and passing it straight
;; into the same fn...

(import 'java.util.concurrent.locks.ReadWriteLock)
(import 'java.util.concurrent.locks.ReentrantReadWriteLock)
(import 'java.util.concurrent.locks.Lock)
(import 'java.util.Map)
(import 'java.util.HashMap)

;; taking a lock, putting an item into a mutable map, releasing the
;; lock appears quicker than swapping a value onto the end of an
;; immutable map in an atom...
(deftest rw-mutable-vs-immutable
  (let [lock ^ReadWriteLock (ReentrantReadWriteLock.)
 	wr (.writeLock lock)
 	m ^Map (HashMap.)
 	a (atom {})
 	n 1000000]
    (is (faster 1
 		(dotimes [i n] (try (.lock wr) (.put m n i) (catch Exception e)(finally (.unlock wr))))
 		(dotimes [i n] (swap! a conj [i i]))
 		))))

;; atom 4 times faster on J6/C1.3a4
;; (if (not (ibm?))
