Merge branch 'dev'

This commit is contained in:
Peter Taoussanis 2013-02-05 20:42:47 +07:00
commit c65e87f335
6 changed files with 53 additions and 26 deletions

View file

@ -1,7 +1,7 @@
Current [semantic](http://semver.org/) version: Current [semantic](http://semver.org/) version:
```clojure ```clojure
[com.taoensso/nippy "1.0.1"] [com.taoensso/nippy "1.1.0"]
``` ```
# Nippy, a Clojure serialization library # 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`: Depend on Nippy in your `project.clj`:
```clojure ```clojure
[com.taoensso/nippy "1.0.1"] [com.taoensso/nippy "1.1.0"]
``` ```
and `require` the library: and `require` the library:
@ -118,7 +118,7 @@ CDS (Clojure Documentation Site) is a contributor-friendly community project aim
## Contact & Contribution ## Contact & Contribution
Reach me (Peter Taoussanis) at *ptaoussanis at gmail.com* for questions/comments/suggestions/whatever. I'm very open to ideas if you have any! I'm also on Twitter: [@ptaoussanis](https://twitter.com/#!/ptaoussanis). Reach me (Peter Taoussanis) at [taoensso.com](https://www.taoensso.com) for questions/comments/suggestions/whatever. I'm very open to ideas if you have any! I'm also on Twitter: [@ptaoussanis](https://twitter.com/#!/ptaoussanis).
## License ## License

View file

@ -1,14 +1,14 @@
(defproject com.taoensso/nippy "1.0.1" (defproject com.taoensso/nippy "1.1.0"
:description "Clojure serialization library" :description "Clojure serialization library"
:url "https://github.com/ptaoussanis/nippy" :url "https://github.com/ptaoussanis/nippy"
:license {:name "Eclipse Public License"} :license {:name "Eclipse Public License"}
:dependencies [[org.clojure/clojure "1.3.0"] :dependencies [[org.clojure/clojure "1.3.0"]
[org.xerial.snappy/snappy-java "1.0.5-M3"]] [org.iq80.snappy/snappy "0.3"]]
:profiles {:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} :profiles {:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]}
:1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]} :1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]}
:1.5 {:dependencies [[org.clojure/clojure "1.5.0-alpha3"]]} :1.5 {:dependencies [[org.clojure/clojure "1.5.0-alpha3"]]}
:dev {:dependencies []} :dev {:dependencies []}
:test {:dependencies []}} :test {:dependencies [[org.xerial.snappy/snappy-java "1.0.5-M3"]]}}
:aliases {"test-all" ["with-profile" "test,1.3:test,1.4:test,1.5" "test"]} :aliases {"test-all" ["with-profile" "test,1.3:test,1.4:test,1.5" "test"]}
:min-lein-version "2.0.0" :min-lein-version "2.0.0"
:warn-on-reflection true) :warn-on-reflection true)

View file

@ -5,7 +5,6 @@
(:require [taoensso.nippy.utils :as utils]) (:require [taoensso.nippy.utils :as utils])
(:import [java.io DataInputStream DataOutputStream ByteArrayOutputStream (:import [java.io DataInputStream DataOutputStream ByteArrayOutputStream
ByteArrayInputStream] ByteArrayInputStream]
[org.xerial.snappy Snappy]
[clojure.lang IPersistentList IPersistentVector IPersistentMap [clojure.lang IPersistentList IPersistentVector IPersistentMap
IPersistentSet PersistentQueue IPersistentCollection Keyword IPersistentSet PersistentQueue IPersistentCollection Keyword
BigInt Ratio])) BigInt Ratio]))
@ -82,8 +81,6 @@
(defprotocol Freezable (freeze [this stream])) (defprotocol Freezable (freeze [this stream]))
(comment (meta '^:DataOutputStream s))
(defmacro freezer (defmacro freezer
"Helper to extend Freezable protocol." "Helper to extend Freezable protocol."
[type id & body] [type id & body]
@ -152,19 +149,22 @@
(defn freeze-to-stream! (defn freeze-to-stream!
"Serializes x to given output stream." "Serializes x to given output stream."
[data-output-stream x] ([data-output-stream x] ; For <= 1.0.1 compatibility
(binding [*print-dup* true] ; For `pr-str` (freeze-to-stream! data-output-stream x true))
(freeze-to-stream!* data-output-stream x))) ([data-output-stream x print-dup?]
(binding [*print-dup* print-dup?] ; For `pr-str`
(freeze-to-stream!* data-output-stream x))))
(defn freeze-to-bytes (defn freeze-to-bytes
"Serializes x to a byte array and returns the array." "Serializes x to a byte array and returns the array."
^bytes [x & {:keys [compress?] ^bytes [x & {:keys [compress? print-dup?]
:or {compress? true}}] :or {compress? true
print-dup? true}}]
(let [ba (ByteArrayOutputStream.) (let [ba (ByteArrayOutputStream.)
stream (DataOutputStream. ba)] stream (DataOutputStream. ba)]
(freeze-to-stream! stream x) (freeze-to-stream! stream x print-dup?)
(let [ba (.toByteArray ba)] (let [ba (.toByteArray ba)]
(if compress? (Snappy/compress ba) ba)))) (if compress? (utils/compress-bytes ba) ba))))
;;;; Thawing ;;;; Thawing
@ -199,10 +199,7 @@
id-list (apply list (coll-thaw! s)) ; TODO OOMs for big colls id-list (apply list (coll-thaw! s)) ; TODO OOMs for big colls
id-vector (into [] (coll-thaw! s)) id-vector (into [] (coll-thaw! s))
id-set (into #{} (coll-thaw! s)) id-set (into #{} (coll-thaw! s))
;; id-map (apply hash-map (coll-thaw! s)) ; OOMs for big colls id-map (into {} (coll-thaw-pairs! s))
;; 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-coll (doall (coll-thaw! s))
id-queue (into (PersistentQueue/EMPTY) (coll-thaw! s)) id-queue (into (PersistentQueue/EMPTY) (coll-thaw! s))
@ -245,7 +242,7 @@
[ba & {:keys [read-eval? compressed?] [ba & {:keys [read-eval? compressed?]
:or {read-eval? false ; For `read-string` injection safety - NB!!! :or {read-eval? false ; For `read-string` injection safety - NB!!!
compressed? true}}] compressed? true}}]
(-> (if compressed? (Snappy/uncompress ba) ba) (-> (if compressed? (utils/uncompress-bytes ba) ba)
(ByteArrayInputStream.) (ByteArrayInputStream.)
(DataInputStream.) (DataInputStream.)
(thaw-from-stream! read-eval?))) (thaw-from-stream! read-eval?)))

View file

@ -14,6 +14,8 @@
(def roundtrip (comp thaw-from-bytes freeze-to-bytes)) (def roundtrip (comp thaw-from-bytes freeze-to-bytes))
(def reader-roundtrip (comp reader-thaw reader-freeze)) (def reader-roundtrip (comp reader-thaw reader-freeze))
(defn autobench [] (bench (roundtrip data)))
(comment (comment
;;; Times ;;; Times
@ -43,4 +45,10 @@
(let [frozen (reader-freeze data)] (count (.getBytes frozen "UTF8"))) (let [frozen (reader-freeze data)] (count (.getBytes frozen "UTF8")))
(let [frozen (freeze-to-bytes data)] (count frozen)) (let [frozen (freeze-to-bytes data)] (count frozen))
;; 22788, 12224 ;; 22788, 12224
;;; Snappy implementations
(println (bench (roundtrip data)))
;; No Snappy: 6163 6064 6042 6176
;; Snappy JNI: 6489 6446 6542 6412
;; Snappy native array copy: 6569 6419 6414 6590
) )

View file

@ -1,6 +1,7 @@
(ns taoensso.nippy.utils (ns taoensso.nippy.utils
{:author "Peter Taoussanis"} {:author "Peter Taoussanis"}
(:require [clojure.string :as str])) (:require [clojure.string :as str])
(:import org.iq80.snappy.Snappy))
(defmacro case-eval (defmacro case-eval
"Like `case` but evaluates test constants for their compile-time value." "Like `case` but evaluates test constants for their compile-time value."
@ -56,3 +57,6 @@
[version-str min-version-str] [version-str min-version-str]
(try (>= (version-compare version-str min-version-str) 0) (try (>= (version-compare version-str min-version-str) 0)
(catch Exception _ false))) (catch Exception _ false)))
(defn compress-bytes [^bytes ba] (Snappy/compress ba))
(defn uncompress-bytes [^bytes ba] (Snappy/uncompress ba 0 (alength ba)))

View file

@ -1,6 +1,7 @@
(ns test-nippy.main (ns test-nippy.main
(:use [clojure.test]) (:use [clojure.test])
(:require [taoensso.nippy :as nippy])) (:require [taoensso.nippy :as nippy]
[taoensso.nippy.benchmarks :as benchmarks]))
;; Remove stuff from stress-data that breaks roundtrip equality ;; Remove stuff from stress-data that breaks roundtrip equality
(def test-data (dissoc nippy/stress-data :bytes)) (def test-data (dissoc nippy/stress-data :bytes))
@ -8,3 +9,20 @@
(def roundtrip (comp nippy/thaw-from-bytes nippy/freeze-to-bytes)) (def roundtrip (comp nippy/thaw-from-bytes nippy/freeze-to-bytes))
(deftest test-roundtrip (is (= test-data (roundtrip test-data)))) (deftest test-roundtrip (is (= test-data (roundtrip test-data))))
(println "Benchmarking roundtrips (x3)")
(println "----------------------------")
(println (benchmarks/autobench))
(println (benchmarks/autobench))
(println (benchmarks/autobench))
(deftest test-snappy-library-compatibility
(let [thaw #(nippy/thaw-from-bytes % :compressed? false)
^bytes raw-ba (nippy/freeze-to-bytes test-data :compress? false)
^bytes xerial-ba (org.xerial.snappy.Snappy/compress raw-ba)
^bytes iq80-ba (org.iq80.snappy.Snappy/compress raw-ba)]
(is (= (thaw raw-ba)
(thaw (org.xerial.snappy.Snappy/uncompress xerial-ba))
(thaw (org.xerial.snappy.Snappy/uncompress iq80-ba))
(thaw (org.iq80.snappy.Snappy/uncompress iq80-ba 0 (alength iq80-ba)))
(thaw (org.iq80.snappy.Snappy/uncompress xerial-ba 0 (alength xerial-ba)))))))