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 22:05
JVM clojure command line args to run with low memory footprint

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 June 24, 2024 14:23
Clojure vs GoLang benchmark - 500 HTTP GET requests

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 July 10, 2024 04:30
When is Clojure "the right tool for the job"?

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 August 20, 2024 20:35
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).
(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 January 5, 2021 22:55
Some Clojure tagged literals to help create functions in various ways, such as create a function that discards any argument passed to it.
;; 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 January 5, 2021 06:32
Example to control Clojure pmap concurrency level using the chunk size of lazy-seqs.
;; 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 January 5, 2021 05:26
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.
(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 October 30, 2020 00:27
A Clojure macro which gives you a let that does not allow shadowing of symbols already declared.
#letnoshadow.clj
@didibus
didibus / user.clj
Created January 29, 2020 04:20
A Clojure user.clj file which lets you lazy load certain namespace at the REPL
(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 January 5, 2023 05:09
Clojure datafy/nav example
#datafy-nav-example