Skip to content

Instantly share code, notes, and snippets.

@alexander-yakushev
Last active September 4, 2023 12:56
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexander-yakushev/63515455759e66bfa19dbaa126fccf56 to your computer and use it in GitHub Desktop.
Save alexander-yakushev/63515455759e66bfa19dbaa126fccf56 to your computer and use it in GitHub Desktop.
System-wide tools.deps configuration and code (for London Clojurians meetup 05'23)
{:deps {org.clojure/clojure {:mvn/version "1.12.0-alpha3"}}
:aliases {:dev {:extra-deps
{com.clojure-goes-fast/clj-async-profiler {:mvn/version "1.0.4"}
com.clojure-goes-fast/clj-java-decompiler {:mvn/version "0.3.4"}
com.clojure-goes-fast/clj-memory-meter {:mvn/version "0.3.0"}}
:jvm-opts ["-Djdk.attach.allowAttachSelf"
"-XX:+UseG1GC"
"-XX:-OmitStackTraceInFastThrow"
"-XX:+UnlockDiagnosticVMOptions" "-XX:+DebugNonSafepoints"]}
:user {:main-opts ["-e" "(load-file,(str,(System/getProperty,\"user.home\"),\"/.clojure/user.clj\"))"]}
:cider {:extra-deps
{nrepl/nrepl {:mvn/version "0.9.0"}
cider/cider-nrepl {:mvn/version "0.30.0"}
refactor-nrepl/refactor-nrepl {:mvn/version "3.6.0"}}
:main-opts ["-m" "nrepl.cmdline" "--middleware" "[refactor-nrepl.middleware/wrap-refactor,cider.nrepl/cider-middleware]"]}}}
;; Additional code to be loaded within user namespace in :dev profile.
(in-ns 'user)
(let [time*
(fn [^long duration-in-ms f]
(let [^com.sun.management.ThreadMXBean bean (java.lang.management.ManagementFactory/getThreadMXBean)
bytes-before (.getCurrentThreadAllocatedBytes bean)
duration (* duration-in-ms 1000000)
start (System/nanoTime)
first-res (f)
delta (- (System/nanoTime) start)
deadline (+ start duration)
tight-iters (max (quot (quot duration delta) 10) 1)]
(loop [i 1]
(let [now (System/nanoTime)]
(if (< now deadline)
(do (dotimes [_ tight-iters] (f))
(recur (+ i tight-iters)))
(let [i' (double i)
bytes-after (.getCurrentThreadAllocatedBytes bean)
t (/ (- now start) i')]
(println
(format "Time per call: %s Alloc per call: %,.0fb Iterations: %d"
(cond (< t 1e3) (format "%.0f ns" t)
(< t 1e6) (format "%.2f us" (/ t 1e3))
(< t 1e9) (format "%.2f ms" (/ t 1e6))
:else (format "%.2f s" (/ t 1e9)))
(/ (- bytes-after bytes-before) i')
i))
first-res))))))]
(defmacro time+
"Like `time`, but runs the supplied body for 2000 ms and prints the average
time for a single iteration. Custom total time in milliseconds can be provided
as the first argument. Returns the returned value of the FIRST iteration."
[?duration-in-ms & body]
(let [[duration body] (if (integer? ?duration-in-ms)
[?duration-in-ms body]
[2000 (cons ?duration-in-ms body)])]
`(~time* ~duration (fn [] ~@body)))))
(defn heap []
(let [u (.getHeapMemoryUsage (java.lang.management.ManagementFactory/getMemoryMXBean))
used (/ (.getUsed u) 1e6)
total (/ (.getMax u) 1e6)]
(format "Used: %.0f/%.0f MB (%.0f%%), free: %.0f MB" used total (/ used total 0.01)
(/ (.freeMemory (Runtime/getRuntime)) 1e6))))
(defmacro debugging-tools []
'(do
(require '[clj-async-profiler.core :as prof])
(require '[clj-java-decompiler.core :refer [decompile]])
(require '[clj-memory-meter.core :as mm])
(.refer *ns* 'time+ #'user/time+)
(.refer *ns* 'heap #'user/heap)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment