Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add lein support; update perf to use criterium.

  • Loading branch information...
commit 8c51a16460e17c1be89595016889bc363520d190 1 parent 13c8444
@ataggart ataggart authored
View
2  .gitignore
@@ -1 +1,3 @@
target/
+bin/
+classes/
View
14 project.clj
@@ -0,0 +1,14 @@
+(defproject org.clojure/data.codec "0.1.1-SNAPSHOT"
+ :description "Clojure codec implementations."
+ :url "https://github.com/clojure/data.codec"
+ :license {:name "Eclipse Public License"
+ :url "http://www.eclipse.org/legal/epl-v10.html"}
+ :source-paths ["src/main/clojure"]
+ :test-paths ["src/test/clojure"]
+ :dependencies [[org.clojure/clojure "1.3.0"]]
+ :aliases {"perf" ["with-profile" "perf" "run"]}
+ :profiles {:test {:dependencies [[commons-codec "1.5"]]}
+ :perf {:dependencies [[commons-codec "1.5"]
+ [criterium "0.4.3"]]
+ :source-paths ["src/perf/clojure"]
+ :main clojure.data.codec.perf-base64}})
View
229 src/perf/clojure/clojure/data/codec/perf_base64.clj
@@ -1,209 +1,32 @@
(ns clojure.data.codec.perf-base64
- (:import [java.io ByteArrayOutputStream PrintWriter]
- org.apache.commons.codec.binary.Base64)
- (:require [clojure.java.io :as io]
- [clojure.string :as str])
- (:use clojure.data.codec.base64))
-
-(comment ;Example usage
-(gen-data "encdata.in" 1 12 20 rand-bytes) ; generate the data file to be used for encoding
-(init-times "encdata.in" "enc.out" 50 enc-apache) ; initialize timing file with apache times
-(add-times "encdata.in" "enc.out" 50 enc-clj) ; add timings for (encode ...)
-(add-times "encdata.in" "enc.out" 50 enc-clj-buf) ; add timings for (encode! ...)
-
-(gen-data "decdata.in" 1 12 20 enc-bytes) ; generate the data file to be used for decoding
-(init-times "decdata.in" "dec.out" 50 dec-apache) ; initialize timing file with apache times
-(add-times "decdata.in" "dec.out" 50 dec-clj) ; add timings for (decode ...)
-(add-times "decdata.in" "dec.out" 50 dec-clj-buf) ; add timings for (decode! ...)
-)
+ (:import org.apache.commons.codec.binary.Base64)
+ (:use clojure.test
+ clojure.data.codec.base64)
+ (:require [criterium.core :as crit]))
(set! *warn-on-reflection* true)
-(defn rand-bytes
- "Returns a randomly populated byte-array of length n."
- [n]
+(defn rand-bytes [n]
(->> #(byte (- (rand-int 256) 128))
- repeatedly
- (take n)
- (byte-array)))
-
-(defn enc-bytes
- "Returns a randomly populated, base64 encoded byte-array of length n."
- [n]
- (encode (rand-bytes n)))
-
-(defn gen-data
- "Prints to file byte vectors generated by gen-fn between lengths from and to,
- inclusive, with times number of each length."
- [file from to times gen-fn]
- (with-open [w (PrintWriter. (io/writer file))]
- (binding [*out* w]
- (doseq [n (range from (inc to))]
- (doseq [_ (range 0 times)]
- (println (into [] (gen-fn n))))))))
-
-(defn read-data
- "Lazily reads a data file, returning a lazy sequence of byte-arrays."
- [file]
- (->> (line-seq (io/reader file))
- (map read-string)
- (map #(map byte %))
- (map byte-array)))
-
-(defmacro time-it
- "Like clojure.core/time, but returns the time in nanos instead of printing it."
- [expr]
- `(let [start# (System/nanoTime)
- _# ~expr
- stop# (System/nanoTime)]
- (- stop# start#)))
-
-(defn enc-clj
- "Returns a lazy sequence of encode timings for the given sequence of byte arrays."
- [bas sleep]
- (for [ba bas]
- (do
- (Thread/sleep sleep)
- (time-it (encode ba)))))
-
-(defn enc-clj-buf
- "Returns a lazy sequence of encode! timings for the given sequence of byte arrays."
- [bas sleep]
- (for [^bytes ba bas]
- (let [len (alength ba)
- output (enc-length len)]
- (do
- (Thread/sleep sleep)
- (time-it (encode! ba 0 len output))))))
-
-(defn enc-clj-xfer
- "Returns a lazy sequence of encoding-transfer timings for the given sequence of byte arrays."
- [bas sleep]
- (for [^bytes ba bas]
- (let [input (io/input-stream ba)
- output (ByteArrayOutputStream. (enc-length (alength ba)))]
- (do
- (Thread/sleep sleep)
- (time-it (encoding-transfer input output))))))
-
-(defn enc-apache
- "Returns a lazy sequence of apache base64 encode timings for the given sequence of
- byte arrays."
- [bas sleep]
- (for [ba bas]
- (do
- (Thread/sleep sleep)
- (time-it (Base64/encodeBase64 ba)))))
-
-(defn dec-clj
- "Returns a lazy sequence of decode timings for the given sequence of byte arrays."
- [bas sleep]
- (for [ba bas]
- (do
- (Thread/sleep sleep)
- (time-it (decode ba)))))
-
-(defn dec-clj-buf
- "Returns a lazy sequence of decode! timings for the given sequence of byte arrays."
- [bas sleep]
- (for [^bytes ba bas]
- (let [len (alength ba)
- output (dec-length len 0)]
- (do
- (Thread/sleep sleep)
- (time-it (decode! ba 0 len output))))))
-
-(defn dec-clj-xfer
- "Returns a lazy sequence of decoding-transfer timings for the given sequence of byte arrays."
- [bas sleep]
- (for [^bytes ba bas]
- (let [input (io/input-stream ba)
- output (ByteArrayOutputStream. (dec-length (alength ba) 0))]
- (do
- (Thread/sleep sleep)
- (time-it (decoding-transfer input output))))))
-
-(defn dec-apache
- "Returns a lazy sequence of apache base64 decode timings for the given sequence of
- byte arrays."
- [bas sleep]
- (for [^bytes ba bas]
- (do
- (Thread/sleep sleep)
- (time-it (Base64/decodeBase64 ba)))))
-
-(defn append-times
- "Lazily adds a column of timings to the given table."
- [table times]
- (map (fnil conj []) table times))
-
-(defn write-times
- "Writes a table of timings to file."
- [table file]
- (with-open [w (PrintWriter. (io/writer file))]
- (binding [*out* w]
- (doseq [row table]
- (print (first row))
- (doseq [e (next row)]
- (print \tab)
- (print e))
- (println)))))
-
-(defn read-times
- "Lazily reads a file containing a table of timings."
- [file]
- (->> (line-seq (io/reader file))
- (map #(str/split % #"\t"))
- (map vec)))
-
-
-(defn third [[_ _ x]] x)
-
-(defn latest-time-file
- "Returns the name of the latest enumerated file with the given basis, or nil if it
- doesn't exist."
- [basis]
- (let [dir (io/file ".")
- nums (->> (.list dir )
- (filter #(.startsWith ^String % basis))
- (map #(re-matches #"(.+\.)([0-9]{3})" %))
- (keep identity)
- (map third)
- (map #(Integer/parseInt %)))]
- (if (seq nums)
- (format "%s.%03d" basis (apply max nums)))))
-
-(defn next-time-file
- "Returns the name of the next enumerated file after the given enumerated file name."
- [file]
- (if-let [[_ prefix suffix] (re-matches #"(.+\.)([0-9]{3})" file)]
- (format "%s%03d" prefix (inc (Integer/parseInt suffix)))))
-
-(defn init-data
- "Returns a lazy sequence of [count apache-timing] for each byte-array."
- [bas perf-fn sleep]
- (map #(vector (count %1) %2) bas (perf-fn bas sleep)))
-
-(defn init-times
- "Using the given data file, creates a timing file using apache base64 encoding.
- Sleep specifies the delay between iterations, thus reducing the chance of delays
- from GC affecting the timing."
- [data-file time-file sleep perf-fn]
- (write-times (init-data (read-data data-file) perf-fn sleep) (str time-file ".000")))
-
-(defn add-times
- "Using the given data file, adds a column of clojure base64 encode times to the
- specified timing file. If use-buffer? is true, encode! will be used instead.
- Sleep specifies the delay between iterations, thus reducing the chance of delays
- from GC affecting the timing."
- [data-file time-file sleep perf-fn]
- (let [prev-time-file (latest-time-file time-file)
- next-time-file (next-time-file prev-time-file)]write-times
- (write-times
- (append-times
- (read-times prev-time-file)
- (perf-fn (read-data data-file) sleep))
- next-time-file)))
-
-
+ (repeatedly n)
+ (byte-array n)))
+
+(defmacro mean [expr]
+ `(-> ~expr (crit/quick-benchmark {}) :mean first))
+
+(defn -main [& _]
+ (let [byte-counts [1e2 1e4 1e6]
+ byte-arrays (map rand-bytes byte-counts)
+ encoded-arrays (map encode byte-arrays)]
+ (binding [crit/*final-gc-problem-threshold* 1]
+ (printf "%23s %14s%n" "base64.clj" "commons-codec")
+ (println "encode:")
+ (flush)
+ (doseq [^bytes ba byte-arrays]
+ (printf "%7dB %ems %ems%n" (alength ba) (mean (encode ba)) (mean (Base64/encodeBase64 ba)))
+ (flush))
+ (println "decode:")
+ (doseq [^bytes ba encoded-arrays]
+ (printf "%7dB %ems %ems%n" (alength ba) (mean (decode ba)) (mean (Base64/decodeBase64 ba)))
+ (flush)))))
Please sign in to comment.
Something went wrong with that request. Please try again.