[英]Efficient binary serialization for Clojure/Java
我正在尋找一種方法來有效地將Clojure對象序列化為二進制格式 - 即不僅僅是做經典的打印和讀取文本序列化。
即我想做的事情:
(def orig-data {:name "Data Object"
:data (get-big-java-array)
:other (get-clojure-data-stuff)})
(def binary (serialize orig-data))
;; here "binary" is a raw binary form, e.g. a Java byte array
;; so it can be persisted in key/value store or sent over network etc.
;; now check it works!
(def new-data (deserialize binary))
(= new-data orig-data)
=> true
我的動機是我有一些包含大量二進制數據的大型數據結構(在Java數組中),我想避免將這些全部轉換為文本並重新轉換回來的開銷。 此外,我正在嘗試保持格式緊湊,以最大限度地減少網絡帶寬使用。
我想要的具體功能:
在Clojure中執行此操作的最佳/標准方法是什么?
我可能在這里遺漏了一些東西,但標准Java序列化有什么問題? 太慢,太大,別的什么?
用於普通Java序列化的Clojure包裝器可能是這樣的:
(defn serializable? [v]
(instance? java.io.Serializable v))
(defn serialize
"Serializes value, returns a byte array"
[v]
(let [buff (java.io.ByteArrayOutputStream. 1024)]
(with-open [dos (java.io.ObjectOutputStream. buff)]
(.writeObject dos v))
(.toByteArray buff)))
(defn deserialize
"Accepts a byte array, returns deserialized value"
[bytes]
(with-open [dis (java.io.ObjectInputStream.
(java.io.ByteArrayInputStream. bytes))]
(.readObject dis)))
user> (= (range 10) (deserialize (serialize (range 10))))
true
有些值無法序列化,例如Java流和Clojure atom / agent / future,但它應該適用於大多數普通值,包括Java原語和數組以及Clojure函數,集合和記錄。
你是否真的保存了什么取決於。 在我對小型數據集的有限測試中,序列化為文本和二進制似乎是大致相同的時間和空間。
但是對於大部分數據是Java基元數組的特殊情況,Java序列化可以快幾個數量級並節省大量空間。 (在筆記本電腦上快速測試,100k隨機字節:序列化0.9毫秒,100kB;文本490毫秒,700kB。)
請注意, (= new-data orig-data)
測試對數組不起作用(它委托給Java的equals
,對於數組只測試它是否是同一個對象),所以你可能想要/需要編寫自己的相等函數測試序列化。
user> (def a (range 10))
user> (= a (range 10))
true
user> (= (into-array a) (into-array a))
false
user> (.equals (into-array a) (into-array a))
false
user> (java.util.Arrays/equals (into-array a) (into-array a))
true
Nippy是imho的最佳選擇之一: https : //github.com/ptaoussanis/nippy
如果您沒有提前架構,則序列化為文本可能是您最好的選擇。 要序列一般任意數據,你需要做大量的工作來保存對象圖,並做反思,看看如何序列一切......至少Clojure的打印機可以做一個靜態的,沒有反射查找print-method
每個項目的print-method
。
相反,如果您真的需要優化的有線格式,則需要定義架構。 我曾經使用過來自java的thrift和來自clojure的protobuf:既不是很有趣,但如果你提前計划的話,這並不是很麻煩。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.