Skip to content

Instantly share code, notes, and snippets.

@didibus
didibus / JVM clojure command line args to run with low memory footprint.md
Last active May 10, 2022
JVM clojure command line args to run with low memory footprint
View JVM clojure command line args to run with low memory footprint.md

If you want to minimimze the memory overhead of the running JVM, as well as make it so the consumed heap size stays as close to the actual ammount of consumed heap from your app, I've found running with the following args to work best:

clojure -J-XX:+UseSerialGC -J-Xmx256m -J-Xms1m -J-Xss256k -J-XX:MaxHeapFreeRatio=10 -J-XX:MinHeapFreeRatio=1 -J-XX:-ShrinkHeapInSteps -J-X
X:TieredStopAtLevel=1
  • SerialGC has the least memory overhead of all GCs, in that it itself doesn't require a lot of memory to run.
  • SerialGC is also good at quickly releasing Heap memory back to the OS if you configure it as such.
  • TieredStopAtLevel=1 will disable C2 compilation, this used to be called -client option in older JDKs, it won't run as fast due to less optimized compilation, but it needs a lot less memory.
@didibus
didibus / $Clojure_vs_GoLang_benchmark_http_get.md
Last active Oct 26, 2021
Clojure vs GoLang benchmark - 500 HTTP GET requests
View $Clojure_vs_GoLang_benchmark_http_get.md

Clojure vs GoLang benchmark - Making 500 HTTP GET requests concurently

Context

In this Gist I wanted to test how quickly Clojure performs 500 HTTP GET requests compared to GO. Surprisingly, using the http-kit Clojure library, a high-performance HTTP client/server implemented in Clojure(and some Java), in turned out that Clojure was faster at fetching http://clojure.org/ 500 times concurently.

I chose http-kit because it is a popular Clojure http client/server, and I did not want to test using

@didibus
didibus / clojure-right-tool.md
Last active Aug 9, 2022
When is Clojure "the right tool for the job"?
View clojure-right-tool.md

My answer to: https://www.reddit.com/r/Clojure/comments/pcwypb/us_engineers_love_to_say_the_right_tool_for_the/ which asked to know when and at what is Clojure "the right tool for the job"?

My take is that in general, the right tool for the job actually doesn't matter that much when it comes to programming language.

There are only a few cases where the options of tools that can do a sufficiently good job at the task become limited.

That's why they are called: General-purpose programming languages, because they can be used generally for most use cases without issues.

Let's look at some of the dimensions that make a difference and what I think of Clojure for them:

@didibus
didibus / complex_business_process_example.clj
Last active Oct 25, 2021
Example of a complex business process to implement in Clojure. Please link to your solutions for alternative ways to implement the same in Clojure (or other languages).
View complex_business_process_example.clj
(ns complex-business-process-example
"A stupid example of a more complex business process to implement as a flowchart.")
;;;; Config
(def config
"When set to :test will trigger the not-boosted branch which won't write to db.
When set to :prod will trigger the boosted branch which will try to write to the db."
{:env :prod})
@didibus
didibus / custom_function_creating_tagged_literals.clj
Last active Jan 5, 2021
Some Clojure tagged literals to help create functions in various ways, such as create a function that discards any argument passed to it.
View custom_function_creating_tagged_literals.clj
;; This one will create a function that takes 0 or more args and discards them all (doesn't use them).
(defn &-tag-reader
[[f & args]]
`(fn [~'& ~'args] (~f ~@args)))
(set! *data-readers* (assoc *data-readers* '& user/&-tag-reader))
(mapv #&(rand-int 5) (range 10))
;;=> [3 0 4 0 2 0 4 4 4 2]
@didibus
didibus / control_pmap_concurrency_level_with_rechunking.clj
Last active Jan 5, 2021
Example to control Clojure pmap concurrency level using the chunk size of lazy-seqs.
View control_pmap_concurrency_level_with_rechunking.clj
;; From: https://clojuredocs.org/clojure.core/chunk#example-5c9cebc3e4b0ca44402ef6ec
(defn re-chunk [n xs]
(lazy-seq
(when-let [s (seq (take n xs))]
(let [cb (chunk-buffer n)]
(doseq [x s] (chunk-append cb x))
(chunk-cons (chunk cb) (re-chunk n (drop n xs)))))))
;; Simply wrap the collection or seq/lazy-seq with re-chunk and the configured chunk size will make pmap's concurrency level grow to the size of the chunk.
(time (dorun (pmap (fn[e] (Thread/sleep 100) (inc e)) (re-chunk 100 (range 1000)))))
@didibus
didibus / agent_concurrently_filter_api_call.clj
Created Jan 5, 2021
Use Clojure agents to concurrently filter out elements from a collection which requires calling a remote API to know if the element should be filtered or not.
View agent_concurrently_filter_api_call.clj
(defn api-pred [e]
(Thread/sleep 100)
(even? e))
(let [coll-to-process (range 1000)
concurrency 100
agents (repeatedly concurrency #(agent []))]
(doseq [[i agnt] (map vector coll-to-process (cycle agents))]
(send-off agnt
#(if (api-pred i)
@didibus
didibus / #letnoshadow.clj
Last active Oct 30, 2020
A Clojure macro which gives you a let that does not allow shadowing of symbols already declared.
View #letnoshadow.clj
#letnoshadow.clj
@didibus
didibus / user.clj
Created Jan 29, 2020
A Clojure user.clj file which lets you lazy load certain namespace at the REPL
View user.clj
(def safe-requires
"List of namespaces to require and refer when inside user ns at load time.
Can be given an initialization body to execute after having been required.
To do so, wrap the lib spec in a vector, and all elements after the lib
spec vector will be evaled after the lib spec has been required."
'[[clojure.repl :as repl :refer (source apropos dir pst doc find-doc)]
[clojure.java.javadoc :as javadoc :refer (javadoc)]
[clojure.pprint :as pprint :refer (pp pprint)]
[clojure.stacktrace :as stacktrace :refer (e)]
@didibus
didibus / #datafy-nav-example
Last active Oct 30, 2020
Clojure datafy/nav example
View #datafy-nav-example
#datafy-nav-example