This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-10-30
Channels
- # announcements (2)
- # babashka (37)
- # beginners (64)
- # biff (27)
- # cherry (7)
- # cider (19)
- # clj-kondo (10)
- # clojure-austin (4)
- # clojure-doc (18)
- # clojure-europe (72)
- # clojure-nl (1)
- # clojure-norway (13)
- # clojure-uk (5)
- # clojurescript (18)
- # data-science (28)
- # events (5)
- # graalvm (32)
- # hyperfiddle (6)
- # introduce-yourself (1)
- # jobs (4)
- # joyride (16)
- # juxt (6)
- # malli (7)
- # missionary (3)
- # off-topic (18)
- # pathom (15)
- # portal (14)
- # re-frame (14)
- # reitit (5)
- # releases (1)
- # rum (2)
- # sci (1)
- # shadow-cljs (102)
- # spacemacs (3)
- # sql (6)
- # web-security (2)
- # xtdb (10)
I want a macro like time
. Tried to copy time
from Clojure core and adapt it like so:
(defmacro timer
"Evaluates expr and prints the time it took. Returns the value of
expr."
[expr]
`(let [start# (js/performance.now)
ret# ~expr]
(prn (str "Elapsed time: " (/ (double (- (js/performance.now) start#)) 1000000.0) " msecs"))
ret#))
Getting Function.prototype.apply was called on undefined, which is a undefined and not a function
when trying to use it. Am I supposed to be able to do something like this?For some definition of “works”. 😃 I’ll need to adapt it to whatever it is I get from performance.now()
…
lol, here is async time: https://github.com/babashka/nbb/blob/e270785599bb9af605d684b02c3ad40b186e736f/src/nbb/macros.clj#L53
I add this to a lot of my JS projects too: https://github.com/babashka/scittle/blob/71c224baa737ae33fb18b8eca064a75dfdeb2a68/src/scittle/core.cljs#L14-L22 I think we should just add it to SCI
I did some benchmarking on some different ways to convert acorn’s AST (which is in some funny JS instance) to plain data. Might as well share.
(ns bench.object-to-data
(:require ["acorn-loose" :as acorn]
[util :as util]
["./ast-util.js" :as ast-util]
["fs" :as fs]))
(defn ast->data [node]
(cond
(array? node) (mapv ast->data (into [] node))
(and node (instance? js/Object node)) (into {} (for [k (js-keys node)
:let [v (aget node k)]]
[(keyword k) (ast->data v)]))
:else node))
(comment
; wc test-files/large.js
; 7662 18943 169040 test-files/large.js
(def text (fs/readFileSync "/Users/pez/.config/joyride/test-files/large.js"))
(util/time ; Elapsed time: 8.087583065032959 msecs
(def ast (acorn.parse text #js {:allowAwaitOutsideFunction true})))
(util/time ; Elapsed time: 5.1631669998168945 msecs
(def js-ast (ast-util/objectAstToData ast)))
(util/time ; Elapsed time: 41.782166957855225 msecs
(def clojure-ast-1 (js->clj js-ast :keywordize-keys true)))
(util/time ; Elapsed time: 201.6672089099884 msecs
(def clojure-ast-2 (ast->data ast)))
(util/time ; Elapsed time: 16.00624990463257 msecs
(def js-ast-2 (-> ast
js/JSON.stringify
js/JSON.parse)))
(util/time ; Elapsed time: 41.43733310699463 msecs
(def clojure-ast-3 (js->clj js-ast-2 :keywordize-keys true)))
:rcf)
The ->js-data converter looks like so:
function objectAstToData(node) {
if (Array.isArray(node)) {
return node.map(objectAstToData);
} else if (node && typeof node === 'object') {
const result = {};
for (const key of Object.keys(node)) {
result[key] = objectAstToData(node[key]);
}
return result;
} else {
return node;
}
}
So:
• 8ms: parsing the file
• 5ms: converting the AST JS data with a JS function
• 16ms: converting the AST to JS data via JSON
• 40ms: js->clj
• 200ms: converting the AST to Clojure data with a SCI CLJS function