diff --git a/README.md b/README.md index c8eb884..b451136 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Current [semantic](http://semver.org/) version: ```clojure -[com.taoensso/nippy "1.0.0"] +[com.taoensso/nippy "1.0.1-SNAPSHOT"] ``` # Nippy, a Clojure serialization library @@ -25,7 +25,7 @@ Nippy is an attempt to provide a drop-in, high-performance alternative to the re Depend on Nippy in your `project.clj`: ```clojure -[com.taoensso/nippy "1.0.0"] +[com.taoensso/nippy "1.0.1-SNAPSHOT"] ``` and `require` the library: diff --git a/benchmarks/benchmarks.clj b/benchmarks/benchmarks.clj index e97de81..4f56786 100644 --- a/benchmarks/benchmarks.clj +++ b/benchmarks/benchmarks.clj @@ -34,6 +34,11 @@ ;; :nippy {:freeze 3751, :thaw 4184, :round 7769}} ;; (float (/ 59545 7769)) = 7.6644354 + ;; Clojure 1.4.0, Nippy 1.0.0 + ;; {:reader {:freeze 22595, :thaw 31148, :round 54059} + ;; :nippy {:freeze 3324, :thaw 3725, :round 6918}} + ;; (float (/ 54059 6918)) = 7.814253 + ;;; Data size (let [frozen (reader-freeze data)] (count (.getBytes frozen "UTF8"))) (let [frozen (freeze-to-bytes data)] (count frozen)) diff --git a/project.clj b/project.clj index f017dc7..94218d8 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject com.taoensso/nippy "1.0.0" +(defproject com.taoensso/nippy "1.0.1-SNAPSHOT" :description "Clojure serialization library" :url "https://github.com/ptaoussanis/nippy" :license {:name "Eclipse Public License"} @@ -11,4 +11,4 @@ :test {:dependencies []}} :aliases {"test-all" ["with-profile" "test,1.3:test,1.4:test,1.5" "test"]} :min-lein-version "2.0.0" - :warn-on-reflection true) \ No newline at end of file + :warn-on-reflection true) diff --git a/src/taoensso/nippy.clj b/src/taoensso/nippy.clj index 0eb8706..78b8ed6 100644 --- a/src/taoensso/nippy.clj +++ b/src/taoensso/nippy.clj @@ -175,6 +175,12 @@ [^DataInputStream s] (repeatedly (.readInt s) (partial thaw-from-stream!* s))) +(defn coll-thaw-pairs! + "Helper to thaw pair-based collection types (e.g. hash maps)." + [^DataInputStream s] + (repeatedly (/ (.readInt s) 2) + (fn [] [(thaw-from-stream!* s) (thaw-from-stream!* s)]))) + (defn- thaw-from-stream!* [^DataInputStream s] (let [type-id (.readByte s)] @@ -190,10 +196,13 @@ id-string (String. (read-bytes! s) "UTF-8") id-keyword (keyword (.readUTF s)) - id-list (apply list (coll-thaw! s)) + id-list (apply list (coll-thaw! s)) ; TODO OOMs for big colls id-vector (into [] (coll-thaw! s)) id-set (into #{} (coll-thaw! s)) - id-map (apply hash-map (coll-thaw! s)) + ;; id-map (apply hash-map (coll-thaw! s)) ; OOMs for big colls + ;; id-map (into {} (map vec (partition 2 (coll-thaw! s))) ; ~6.4x time + ;; id-map (into {} (utils/pairs (coll-thaw! s))) ; ~1.8x time + id-map (into {} (coll-thaw-pairs! s)) ; ~0.8x time id-coll (doall (coll-thaw! s)) id-queue (into (PersistentQueue/EMPTY) (coll-thaw! s)) diff --git a/src/taoensso/nippy/utils.clj b/src/taoensso/nippy/utils.clj index b70941e..17be404 100644 --- a/src/taoensso/nippy/utils.clj +++ b/src/taoensso/nippy/utils.clj @@ -13,6 +13,14 @@ clauses) ~(when default default)))) +(defn pairs + "Like (partition 2 coll) but faster and returns lazy seq of vector pairs." + [coll] + (lazy-seq + (when-let [s (seq coll)] + (let [n (next s)] + (cons [(first s) (first n)] (pairs (next n))))))) + (defmacro time-ns "Returns number of nanoseconds it takes to execute body." [& body]