From 8b7186a9306072b3449501faf9e68a8413e378e1 Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Tue, 1 Aug 2023 12:19:25 +0200 Subject: [PATCH] [nop] Update benchmark results --- benchmarks.png | Bin 20896 -> 123987 bytes src/taoensso/nippy.clj | 16 +- src/taoensso/nippy/benchmarks.clj | 241 +++++++++++++----------------- test/taoensso/nippy_tests.clj | 4 +- 4 files changed, 111 insertions(+), 150 deletions(-) diff --git a/benchmarks.png b/benchmarks.png index af745589e280a3c087b253ee11637cad47b2767c..1c2a6179d7a0288415b201870e25ae55891bf29d 100644 GIT binary patch literal 123987 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 P@a5(1zwNPG@DKk3FBNw_ literal 20896 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 LoWqo!c8vG~jk84F diff --git a/src/taoensso/nippy.clj b/src/taoensso/nippy.clj index 942ab43..c669aff 100644 --- a/src/taoensso/nippy.clj +++ b/src/taoensso/nippy.clj @@ -2103,15 +2103,19 @@ :ex-info (ex-info "ExInfo" {:data "data"})}) (def stress-data-comparable - "Reference data with stuff removed that breaks roundtrip equality" - (dissoc stress-data :bytes :throwable :exception :ex-info :regex :objects)) + "Reference data with stuff removed that breaks roundtrip equality." + (dissoc stress-data :bytes :objects :throwable :exception :ex-info :regex)) + +(comment (let [data stress-data-comparable] (= (thaw (freeze data)) data))) (def stress-data-benchable "Reference data with stuff removed that breaks reader or other utils we'll - be benching against" - (dissoc stress-data - :bytes :throwable :exception :ex-info :queue :queue-empty - :byte :stress-record :stress-type :regex :objects)) + be benching with." + (dissoc stress-data-comparable + :queue :queue-empty + :stress-record :stress-type + :time-instant :time-duration :time-period + :byte :uri)) ;;;; Tools diff --git a/src/taoensso/nippy/benchmarks.clj b/src/taoensso/nippy/benchmarks.clj index 21b9ed3..d851b33 100644 --- a/src/taoensso/nippy/benchmarks.clj +++ b/src/taoensso/nippy/benchmarks.clj @@ -1,168 +1,127 @@ (ns taoensso.nippy.benchmarks "Nippy benchmarks." - (:require [clojure.data.fressian :as fressian] - [taoensso.encore :as enc] - [taoensso.nippy :as nippy :refer [freeze thaw]])) + (:require + [clojure.data.fressian :as fress] + [taoensso.encore :as enc] + [taoensso.nippy :as nippy])) -(def data #_22 nippy/stress-data-benchable) +;;;; Reader -(defn fressian-freeze [value] - (let [^java.nio.ByteBuffer bb (fressian/write value) +(defn- freeze-reader [x] (enc/pr-edn x)) +(defn- thaw-reader [edn] (enc/read-edn edn)) + +;;;; Fressian + +(defn- freeze-fress [x] + (let [^java.nio.ByteBuffer bb (fress/write x) len (.remaining bb) ba (byte-array len)] (.get bb ba 0 len) - ba)) + (do ba))) -(defn fressian-thaw [value] - (let [bb (java.nio.ByteBuffer/wrap value)] - (fressian/read bb))) +(defn- thaw-fress [^bytes ba] + (let [bb (java.nio.ByteBuffer/wrap ba)] + (fress/read bb))) -(comment (fressian-thaw (fressian-freeze data))) +(comment (-> data freeze-fress thaw-fress)) -(defmacro bench* [& body] `(enc/bench 10000 {:warmup-laps 25000} ~@body)) -(defn bench1 [freezer thawer & [sizer]] - (let [data-frozen (freezer data) - time-freeze (bench* (freezer data)) - time-thaw (bench* (thawer data-frozen))] - {:round (+ time-freeze time-thaw) - :freeze time-freeze - :thaw time-thaw - :size ((or sizer count) data-frozen)})) +;;;; Benchable data -(defn bench [{:keys [reader? lzma2? fressian? laps] :or {laps 1}}] - (println "\nBenching (this can take some time)") - (println "----------------------------------") - (dotimes [l laps] - (println (str "\nLap " (inc l) "/" laps "...")) - - (when reader? ; Slow - (println {:reader (bench1 enc/pr-edn enc/read-edn - #(count (.getBytes ^String % "UTF-8")))})) - - (when lzma2? ; Slow - (println {:lzma2 (bench1 #(freeze % {:compressor nippy/lzma2-compressor}) - #(thaw % {:compressor nippy/lzma2-compressor}))})) - - (when fressian? - (println {:fressian (bench1 fressian-freeze fressian-thaw)})) - - (println {:encrypted (bench1 #(freeze % {:password [:cached "p"]}) - #(thaw % {:password [:cached "p"]}))}) - (println {:default (bench1 #(freeze % {}) - #(thaw % {}))}) - (println {:fast (bench1 nippy/fast-freeze nippy/fast-thaw)})) - - (println "\nDone! (Time for cake?)") - true) - -(comment (enc/read-edn (enc/pr-edn data)) - (bench1 fressian-freeze fressian-thaw)) +(def data + "Map of data suitable for benching, a subset of + `nippy/stress-data-comparable`." + (reduce-kv + (fn [m k v] + (try + (-> v freeze-reader thaw-reader) + (-> v freeze-fress thaw-fress) + m + (catch Throwable _ (dissoc m k)))) + nippy/stress-data-comparable + nippy/stress-data-comparable)) (comment - (set! *unchecked-math* false) - ;; (bench {:reader? true :lzma2? true :fressian? true :laps 2}) - ;; (bench {:laps 2}) + (clojure.set/difference + (set (keys nippy/stress-data-comparable)) + (set (keys data)))) - ;;; 2016 Jul 17, v2.12.0-RC2, minor final optimizations - {:encrypted {:round 4527, :freeze 2651, :thaw 1876, :size 16324}} - {:default {:round 3998, :freeze 2226, :thaw 1772, :size 16297}} - {:fast {:round 3408, :freeze 1745, :thaw 1663, :size 17069}} +;;;; - ;;; 2016 Apr 14, v2.12.0-SNAPSHOT, refactor + larger data + new hardware - {:reader {:round 52380, :freeze 17817, :thaw 34563, :size 27861}} - {:lzma2 {:round 43321, :freeze 28312, :thaw 15009, :size 11260}} - {:fressian {:round 6911, :freeze 5109, :thaw 1802, :size 17105}} - {:encrypted {:round 4726, :freeze 2951, :thaw 1775, :size 16308}} - {:default {:round 4299, :freeze 2655, :thaw 1644, :size 16278}} - {:fast {:round 3739, :freeze 2159, :thaw 1580, :size 17069}} - ;; 12.184228890439638 :default - ;; 14.009093340465364 :fast +(defn- bench1 + [{:keys [laps warmup] :or {laps 1e4, warmup 25e3}} freezer thawer sizer] + (let [data-frozen (freezer data) + time-freeze (enc/bench laps {:warmup-laps warmup} (freezer data)) + time-thaw (enc/bench laps {:warmup-laps warmup} (thawer data-frozen)) + data-size (sizer data-frozen)] - ;;; 2015 Oct 6, v2.11.0-alpha4 - {:reader {:round 73409, :freeze 21823, :thaw 51586, :size 27672}} - {:lzma2 {:round 56689, :freeze 37222, :thaw 19467, :size 11252}} - {:fressian {:round 10666, :freeze 7737, :thaw 2929, :size 16985}} - {:encrypted {:round 6885, :freeze 4227, :thaw 2658, :size 16148}} - {:default {:round 6304, :freeze 3824, :thaw 2480, :size 16122}} - {:fast1 {:round 5352, :freeze 3272, :thaw 2080, :size 16976}} - {:fast2 {:round 5243, :freeze 3238, :thaw 2005, :size 16972}} - ;; :reader/:default ratio: 11.64 - ;; - {:reader {:round 26, :freeze 17, :thaw 9, :size 2}} - {:lzma2 {:round 3648, :freeze 3150, :thaw 498, :size 68}} - {:fressian {:round 19, :freeze 7, :thaw 12, :size 1}} - {:encrypted {:round 63, :freeze 40, :thaw 23, :size 36}} - {:default {:round 24, :freeze 17, :thaw 7, :size 6}} - {:fast1 {:round 19, :freeze 12, :thaw 7, :size 6}} - {:fast2 {:round 4, :freeze 2, :thaw 2, :size 2}} + {:round (+ time-freeze time-thaw) + :freeze time-freeze + :thaw time-thaw + :size data-size})) - ;;; 2015 Sep 29, after read/write API refactor - {:lzma2 {:round 51640, :freeze 33699, :thaw 17941, :size 11240}} - {:encrypted {:round 5922, :freeze 3734, :thaw 2188, :size 16132}} - {:default {:round 5588, :freeze 3658, :thaw 1930, :size 16113}} - {:fast {:round 4533, :freeze 2688, :thaw 1845, :size 16972}} +(comment (bench1 {} nippy/freeze nippy/thaw count)) - ;;; 2015 Sep 28, small collection optimizations - {:lzma2 {:round 56307, :freeze 36475, :thaw 19832, :size 11244}} - {:encrypted {:round 6062, :freeze 3802, :thaw 2260, :size 16148}} - {:default {:round 5482, :freeze 3382, :thaw 2100, :size 16128}} - {:fast {:round 4729, :freeze 2826, :thaw 1903, :size 16972}} +(defn bench + [{:keys [all? reader? fressian? fressian? lzma2? laps warmup] + :or {laps 1e4 + warmup 25e3}}] - ;;; 2015 Sep 29, various micro optimizations (incl. &arg elimination) - {:reader {:round 63547, :freeze 19374, :thaw 44173, :size 27717}} - {:lzma2 {:round 51724, :freeze 33502, :thaw 18222, :size 11248}} - {:fressian {:round 8813, :freeze 6460, :thaw 2353, :size 16985}} - {:encrypted {:round 6005, :freeze 3768, :thaw 2237, :size 16164}} - {:default {:round 5417, :freeze 3354, :thaw 2063, :size 16145}} - {:fast {:round 4659, :freeze 2712, :thaw 1947, :size 17026}} + (println "\nStarting benchmarks") + (println "---") - ;;; 2015 Sep 15 - v2.10.0-alpha6, Clojure 1.7.0 - {:reader {:round 94901, :freeze 25781, :thaw 69120, :size 27686}} - {:lzma2 {:round 65127, :freeze 43150, :thaw 21977, :size 11244}} - {:encrypted {:round 12590, :freeze 7565, :thaw 5025, :size 16148}} - {:fressian {:round 12085, :freeze 9168, :thaw 2917, :size 16972}} - {:default {:round 6974, :freeze 4582, :thaw 2392, :size 16123}} - {:fast {:round 6255, :freeze 3724, :thaw 2531, :size 17013}} + (let [results_ (atom {})] + (when (or all? reader?) + (println "Benching Reader...") + (swap! results_ assoc :reader + (bench1 {:laps laps, :warmup warmup} + freeze-reader thaw-reader + (fn [^String s] (count (.getBytes s "UTF-8")))))) - ;;; 2015 Sep 14 - v2.10.0-alpha5, Clojure 1.7.0-RC1 - {:default {:round 6870, :freeze 4376, :thaw 2494, :size 16227}} - {:fast {:round 6104, :freeze 3743, :thaw 2361, :size 17013}} - {:encrypted {:round 12155, :freeze 6908, :thaw 5247, :size 16244}} + (when (or all? fressian?) + (println "- Benching Fressian...") + (swap! results_ assoc :fressian (bench1 {:laps laps, :warmup warmup} freeze-fress thaw-fress count))) - ;;; 2015 June 4 - v2.9.0, Clojure 1.7.0-RC1 - {:reader {:round 155353, :freeze 44192, :thaw 111161, :size 27693}} - {:lzma2 {:round 102484, :freeze 68274, :thaw 34210, :size 11240}} - {:fressian {:round 44665, :freeze 34996, :thaw 9669, :size 16972}} - {:encrypted {:round 19791, :freeze 11354, :thaw 8437, :size 16148}} - {:default {:round 12302, :freeze 8310, :thaw 3992, :size 16126}} - {:fast {:round 9802, :freeze 5944, :thaw 3858, :size 17013}} + (when (or all? lzma2?) + (println "- Benching Nippy/LZMA2...") + (swap! results_ assoc :nippy/lzma2 + (bench1 {:laps laps, :warmup warmup} + #(nippy/freeze % {:compressor nippy/lzma2-compressor}) + #(nippy/thaw % {:compressor nippy/lzma2-compressor}) + count))) - ;;; 2015 Apr 17 w/ smart compressor selection, Clojure 1.7.0-beta1 - {:default {:round 6163, :freeze 4095, :thaw 2068, :size 16121}} - {:fast {:round 5417, :freeze 3480, :thaw 1937, :size 17013}} - {:encrypted {:round 10950, :freeze 6400, :thaw 4550, :size 16148}} + (println "- Benching Nippy/encrypted...") + (swap! results_ assoc :nippy/encrypted + (bench1 {:laps laps, :warmup warmup} + #(nippy/freeze % {:password [:cached "p"]}) + #(nippy/thaw % {:password [:cached "p"]}) + count)) - ;;; 2014 Apr 7 w/ some additional implementation tuning - {:default {:round 6533, :freeze 3618, :thaw 2915, :size 16139}} - {:fast {:round 6250, :freeze 3376, :thaw 2874, :size 16992}} - {:encrypted {:round 10583, :freeze 5581, :thaw 5002, :size 16164}} + (println "- Benching Nippy/default...") + (swap! results_ assoc :nippy/default (bench1 {:laps laps, :warmup warmup} nippy/freeze nippy/thaw count)) - ;;; 2014 Apr 5 w/ headerless :fast, LZ4 replacing Snappy as default compressor - {:default {:round 7039, :freeze 3865, :thaw 3174, :size 16123}} - {:fast {:round 6394, :freeze 3379, :thaw 3015, :size 16992}} - {:encrypted {:round 11035, :freeze 5860, :thaw 5175, :size 16148}} + (println "- Benching Nippy/fast...") + (swap! results_ assoc :nippy/fast (bench1 {:laps laps, :warmup warmup} nippy/fast-freeze nippy/fast-thaw count)) - ;;; 2014 Jan 22: with common-type size optimizations, enlarged stress-data - {:reader {:round 109544, :freeze 39523, :thaw 70021, :size 27681}} - {:default {:round 9234, :freeze 5128, :thaw 4106, :size 15989}} - {:fast {:round 7402, :freeze 4021, :thaw 3381, :size 16957}} - {:encrypted {:round 12594, :freeze 6884, :thaw 5710, :size 16020}} - {:lzma2 {:round 66759, :freeze 44246, :thaw 22513, :size 11208}} - {:fressian {:round 13052, :freeze 8694, :thaw 4358, :size 16942}} + (println "- Benchmarks complete! (Time for cake?)") - ;;; 19 Oct 2013: Nippy v2.3.0, with lzma2 & (nb!) round=freeze+thaw - {:reader {:round 67798, :freeze 23202, :thaw 44596, :size 22971}} - {:default {:round 3632, :freeze 2349, :thaw 1283, :size 12369}} - {:encrypted {:round 6970, :freeze 4073, :thaw 2897, :size 12388}} - {:fast {:round 3294, :freeze 2109, :thaw 1185, :size 13277}} - {:lzma2 {:round 44590, :freeze 29567, :thaw 15023, :size 9076}}) + (let [results @results_] + (println "\n") + (doseq [[k v] results] (println k " " v)) + (do results)))) + +(comment + (do + (set! *unchecked-math* false) + (bench {:all? true})) + + ;; 2023 Aug 1, 2020 Apple MBP M1 + ;; [com.taoensso/nippy "3.2.0"] + ;; [org.clojure/tools.reader "1.3.6"] + ;; [org.clojure/data.fressian "1.0.0"] + + {:reader {:round 35041, :freeze 5942, :thaw 29099, :size 39389} + :fressian {:round 6241, :freeze 3429, :thaw 2812, :size 22850} + :nippy/lzma2 {:round 33561, :freeze 20530, :thaw 13031, :size 11444} + :nippy/encrypted {:round 3390, :freeze 1807, :thaw 1583, :size 16468} + :nippy/default {:round 2845, :freeze 1513, :thaw 1332, :size 16440} + :nippy/fast {:round 2634, :freeze 1338, :thaw 1296, :size 28454}}) diff --git a/test/taoensso/nippy_tests.clj b/test/taoensso/nippy_tests.clj index 644132d..a63b884 100644 --- a/test/taoensso/nippy_tests.clj +++ b/test/taoensso/nippy_tests.clj @@ -393,6 +393,4 @@ ;;;; Benchmarks -(deftest _benchmarks - (is (benchmarks/bench {})) ; Also tests :cached passwords - ) +(deftest _benchmarks (is (benchmarks/bench {})))