Skip to content

Instantly share code, notes, and snippets.

@pangloss
Created August 25, 2014 00:23
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pangloss/591d77231fda460c2fbe to your computer and use it in GitHub Desktop.
Save pangloss/591d77231fda460c2fbe to your computer and use it in GitHub Desktop.
js->clj benchmarks
(ns js-to-clj-bench.core)
; Run this benchmark at: http://jsperf.com/js-clj-transducer-test
(let [data
"[{ \"web-app\": { \"servlet\": [ { \"servlet-name\": \"cofaxCDS\", \"servlet-class\": \"org.cofax.cds.CDSServlet\", \"init-param\": { \"configGlossary:installationAt\": \"Philadelphia, PA\", \"configGlossary:adminEmail\": \"ksm@pobox.com\", \"configGlossary:poweredBy\": \"Cofax\", \"configGlossary:poweredByIcon\": \"/images/cofax.gif\", \"configGlossary:staticPath\": \"/content/static\", \"templateProcessorClass\": \"org.cofax.WysiwygTemplate\", \"templateLoaderClass\": \"org.cofax.FilesTemplateLoader\", \"templatePath\": \"templates\" } }, { \"servlet-name\": \"cofaxAdmin\", \"servlet-class\": \"org.cofax.cds.AdminServlet\" }, { \"servlet-name\": \"cofaxTools\", \"servlet-class\": \"org.cofax.cms.CofaxToolsServlet\", \"init-param\": { \"templatePath\": \"toolstemplates/\", \"log\": 1, \"logLocation\": \"/usr/local/tomcat/logs/CofaxTools.log\", \"logMaxSize\": \"\", \"dataLog\": 1, \"dataLogLocation\": \"/usr/local/tomcat/logs/dataLog.log\", \"dataLogMaxSize\": \"\", \"removePageCache\": \"/content/admin/remove?cache=pages&id=\", \"removeTemplateCache\": \"/content/admin/remove?cache=templates&id=\", \"fileTransferFolder\": \"/usr/local/tomcat/webapps/content/fileTransferFolder\", \"lookInContext\": 1, \"adminGroupID\": 4, \"betaServer\": true } } ], \"servlet-mapping\": { \"cofaxCDS\": \"/\", \"cofaxEmail\": \"/cofaxutil/aemail/*\", \"cofaxAdmin\": \"/admin/*\", \"fileServlet\": \"/static/*\", \"cofaxTools\": \"/tools/*\" }, \"taglib\": { \"taglib-uri\": \"cofax.tld\", \"taglib-location\": \"/WEB-INF/tlds/cofax.tld\" } } },
{\"menu\": { \"id\": \"file\", \"value\": \"File\", \"popup\": { \"menuitem\": [ {\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"}, {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"}, {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"} ] } }} ]"
]
(def js-data (js/JSON.parse data)))
(defn new-js->clj
"Recursively transforms JavaScript arrays into ClojureScript
vectors, and JavaScript objects into ClojureScript maps. With
option ':keywordize-keys true' will convert object fields from
strings to keywords."
([x] (new-js->clj x {:keywordize-keys false}))
([x & opts]
(cond
(satisfies? IEncodeClojure x)
(-js->clj x (apply array-map opts))
(seq opts)
(let [{:keys [keywordize-keys]} opts
keyfn (if keywordize-keys keyword str)
f (fn thisfn [x]
(cond
(seq? x)
(doall (map thisfn x))
(coll? x)
(into (empty x) (map thisfn) x)
(array? x)
(into [] (map thisfn) x)
(identical? (type x) js/Object)
(into {} (map (fn [k] [(keyfn k) (thisfn (aget x k))])) (js-keys x))
:else x))]
(f x)))))
(defn new-js->clj2
"Recursively transforms JavaScript arrays into ClojureScript
vectors, and JavaScript objects into ClojureScript maps. With
option ':keywordize-keys true' will convert object fields from
strings to keywords."
([x] (new-js->clj2 x {:keywordize-keys false}))
([x & opts]
(cond
(satisfies? IEncodeClojure x)
(-js->clj x (apply array-map opts))
(seq opts)
(let [{:keys [keywordize-keys]} opts
keyfn (if keywordize-keys keyword str)
f (fn thisfn [x]
(cond
(seq? x)
(doall (map thisfn x))
(coll? x)
(into (empty x) (map thisfn) x)
(array? x)
(into [] (map thisfn) x)
(identical? (type x) js/Object)
(persistent!
(reduce (fn [r k] (assoc! r (keyfn k) (thisfn (aget x k))))
(transient {}) (js-keys x)))
:else x))]
(f x)))))
(defn new-js->clj3
"Recursively transforms JavaScript arrays into ClojureScript
vectors, and JavaScript objects into ClojureScript maps. With
option ':keywordize-keys true' will convert object fields from
strings to keywords."
([x] (new-js->clj3 x {:keywordize-keys false}))
([x & opts]
(cond
(satisfies? IEncodeClojure x)
(-js->clj x (apply array-map opts))
(seq opts)
(let [{:keys [keywordize-keys]} opts
keyfn (if keywordize-keys keyword str)
f (fn thisfn [x]
(cond
(seq? x)
(doall (map thisfn x))
(coll? x)
(into (empty x) (map thisfn) x)
(array? x)
(persistent!
(reduce #(conj! %1 (thisfn %2))
(transient []) x))
(identical? (type x) js/Object)
(persistent!
(reduce (fn [r k] (assoc! r (keyfn k) (thisfn (aget x k))))
(transient {}) (js-keys x)))
:else x))]
(f x)))))
(defn ^:export old-way []
(js->clj js-data))
(defn ^:export new-way []
(new-js->clj js-data))
(defn ^:export new-way2 []
(new-js->clj2 js-data))
(defn ^:export new-way3 []
(new-js->clj3 js-data))
@danielo515
Copy link

Have you executed the tests? What are the results?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment