rlm@0
|
1 (ns rlm.iterate
|
rlm@0
|
2 "from the clojure mailing list"
|
rlm@0
|
3 {:author "tsuraan"}
|
rlm@0
|
4 (:gen-class
|
rlm@0
|
5 :name "iterate"
|
rlm@0
|
6 :main true
|
rlm@0
|
7 ))
|
rlm@0
|
8
|
rlm@0
|
9
|
rlm@0
|
10 (set! *warn-on-reflection* true)
|
rlm@0
|
11 (import java.io.FileInputStream)
|
rlm@0
|
12
|
rlm@0
|
13 (def *numbytes* (* 16 1024 1024))
|
rlm@0
|
14
|
rlm@0
|
15
|
rlm@0
|
16 (defmacro better-areduce [a idx ret init expr]
|
rlm@0
|
17 `(let [a# ~a
|
rlm@0
|
18 alength# (alength a#)]
|
rlm@0
|
19 (loop [~idx (int 0) ~ret ~init]
|
rlm@0
|
20 (if (< ~idx alength#)
|
rlm@0
|
21 (recur (unchecked-inc ~idx) ~expr)
|
rlm@0
|
22 ~ret))))
|
rlm@0
|
23
|
rlm@0
|
24 (defn translated-countnl
|
rlm@0
|
25 [#^bytes buf]
|
rlm@0
|
26 (let [total-length (alength buf)]
|
rlm@0
|
27 (loop [count (int 0) current-index (int 0)]
|
rlm@0
|
28 (if (>= current-index total-length)
|
rlm@0
|
29 count
|
rlm@0
|
30 (let [new-count
|
rlm@0
|
31 (if (= (aget #^bytes buf current-index) (byte 10))
|
rlm@0
|
32 (unchecked-inc count)
|
rlm@0
|
33 count)]
|
rlm@0
|
34
|
rlm@0
|
35 (recur new-count (unchecked-inc current-index)))))))
|
rlm@0
|
36
|
rlm@0
|
37 (defn countnl-classic
|
rlm@0
|
38 [#^bytes buf]
|
rlm@0
|
39 (let [nl (byte 10)]
|
rlm@0
|
40 (areduce buf idx count 0
|
rlm@0
|
41 (if (= (aget buf idx) nl)
|
rlm@0
|
42 (inc count)
|
rlm@0
|
43 count))))
|
rlm@0
|
44
|
rlm@0
|
45
|
rlm@0
|
46 (defn countnl-lite
|
rlm@0
|
47 "this is the absolute fastest function I could come up with.
|
rlm@0
|
48 still 2.25 times slower that the java version."
|
rlm@0
|
49 [#^bytes buf]
|
rlm@0
|
50 (areduce buf idx count (int 0)
|
rlm@0
|
51 (if (= (clojure.lang.RT/aget buf idx) 10)
|
rlm@0
|
52 (unchecked-add count 1)
|
rlm@0
|
53 count)))
|
rlm@0
|
54
|
rlm@0
|
55
|
rlm@0
|
56 (defn #^Boolean is-ten? [#^Integer A]
|
rlm@0
|
57 (= A 10))
|
rlm@0
|
58
|
rlm@0
|
59 (defn countnl-max-power
|
rlm@0
|
60 [#^bytes buf]
|
rlm@0
|
61 (areduce buf idx count (int 0)
|
rlm@0
|
62 (if (is-ten? (clojure.lang.RT/aget buf idx))
|
rlm@0
|
63 (unchecked-inc count)
|
rlm@0
|
64 count)))
|
rlm@0
|
65
|
rlm@0
|
66
|
rlm@0
|
67
|
rlm@0
|
68
|
rlm@0
|
69
|
rlm@0
|
70
|
rlm@0
|
71
|
rlm@0
|
72
|
rlm@0
|
73
|
rlm@0
|
74
|
rlm@0
|
75
|
rlm@0
|
76 "(times are averages with 10 rounds)
|
rlm@0
|
77 no-modifications
|
rlm@0
|
78 classic: 198.151
|
rlm@0
|
79 lite: 186.668
|
rlm@0
|
80
|
rlm@0
|
81 unchecked-inc
|
rlm@0
|
82 classic: 177.938
|
rlm@0
|
83 lite: 129.604
|
rlm@0
|
84
|
rlm@0
|
85 inlined-let
|
rlm@0
|
86 classic: 202.604
|
rlm@0
|
87 lite: 195.357
|
rlm@0
|
88
|
rlm@0
|
89 make nl a constant
|
rlm@0
|
90 classic:
|
rlm@0
|
91 lite: 361.734
|
rlm@0
|
92
|
rlm@0
|
93 make nl a constant with type hint
|
rlm@0
|
94 lite: 394.45
|
rlm@0
|
95
|
rlm@0
|
96 literal 10, no let
|
rlm@0
|
97 lite: 102.876
|
rlm@0
|
98
|
rlm@0
|
99 (int 10) instead of literal 10
|
rlm@0
|
100 lite: 194.904
|
rlm@0
|
101
|
rlm@0
|
102 (unchecked-add count 0) instead of count
|
rlm@0
|
103 lite: 209.186
|
rlm@0
|
104
|
rlm@0
|
105 direct reference to RT/aget, bypassing int cast
|
rlm@0
|
106 lite: 99.767
|
rlm@0
|
107
|
rlm@0
|
108 (int 0) instead of 0 initialization of count
|
rlm@0
|
109 lite: 66.446
|
rlm@0
|
110
|
rlm@0
|
111 make nl an (int 10) instead of (byte 10)
|
rlm@0
|
112 lite: 180.003
|
rlm@0
|
113 "
|
rlm@0
|
114
|
rlm@0
|
115
|
rlm@0
|
116
|
rlm@0
|
117
|
rlm@0
|
118
|
rlm@0
|
119 (defmacro time-multi
|
rlm@0
|
120 "Evaluates expr and prints the time it took. Returns the value of
|
rlm@0
|
121 expr."
|
rlm@0
|
122 {:added "1.0"}
|
rlm@0
|
123 [expr]
|
rlm@0
|
124 `(let [start# (. System (nanoTime))
|
rlm@0
|
125 ret# ~expr
|
rlm@0
|
126 end# (/ (double (- (. System (nanoTime)) start#)) 1000000.0)]
|
rlm@0
|
127 (prn (str "Elapsed time: " end# " msecs"))
|
rlm@0
|
128 [ret# end#]))
|
rlm@0
|
129
|
rlm@0
|
130
|
rlm@0
|
131
|
rlm@0
|
132 (defn run [countnl-impl]
|
rlm@0
|
133 (let [ifs (FileInputStream. "/dev/urandom")
|
rlm@0
|
134 buf (make-array Byte/TYPE *numbytes*)
|
rlm@0
|
135 runs 10]
|
rlm@0
|
136 (loop [n 0 total-time 0]
|
rlm@0
|
137 (if (= n runs) (/ total-time runs)
|
rlm@0
|
138 (let [sz (.read #^FileInputStream ifs buf)]
|
rlm@0
|
139 (println "Wanted" *numbytes* "got" sz "bytes")
|
rlm@0
|
140 (let [[count time] (time-multi (countnl-impl buf))]
|
rlm@0
|
141 (println "Got" count "nls")
|
rlm@0
|
142 (recur (inc n) (+ total-time time))))))))
|
rlm@0
|
143
|
rlm@0
|
144 (defn -main [& ignore]
|
rlm@0
|
145 (run countnl-lite)
|
rlm@0
|
146 (run countnl-classic)
|
rlm@0
|
147 )
|
rlm@0
|
148
|
rlm@0
|
149
|
rlm@0
|
150
|