Skip to content

Commit e30cbfc

Browse files
authored
Clojure/solution_3: build executable jar (PlummersSoftwareLLC#825)
1 parent 84d505c commit e30cbfc

File tree

9 files changed

+85
-33
lines changed

9 files changed

+85
-33
lines changed

PrimeClojure/solution_3/.dockerignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Dockerfile
2+
README.md
3+
.gitignore
4+
classes
5+
target

PrimeClojure/solution_3/.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
classes/
66
.lsp/.cache/
77
.clj-condo/.cache/
8-
decompiled*.java
8+
decompiled*.java
9+
target/

PrimeClojure/solution_3/Dockerfile

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
FROM clojure:openjdk-18-tools-deps
2+
23
WORKDIR /primes
3-
COPY deps.edn sieve.clj run.sh ./
4+
5+
COPY . ./
6+
RUN ./build.sh
7+
48
ENTRYPOINT ["./run.sh"]

PrimeClojure/solution_3/README.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,25 @@ The other implementations either start with all numbers, even and odd, or use so
2626
The runner infrastructure is built from Alex Vear's [Clojure Solution 2](https://github.com/PlummersSoftwareLLC/Primes/tree/drag-race/PrimeClojure/solution_2).
2727

2828
1. Install a JDK.
29-
2. Install the [Clojure CLI tools](https://clojure.org/guides/getting_started#_clojure_installer_and_cli_tools).
30-
3. Run with `clojure -X sieve/run :warm-up? true`
29+
1. Install the [Clojure CLI tools](https://clojure.org/guides/getting_started#_clojure_installer_and_cli_tools).
30+
1. Run with `clojure -X sieve/run :variant :boolean-array ':warm-up?' true`
3131

3232
The warm-up makes the runner start with a silent run, before running one that is reported, giving slightly more consistent results. (But, really, you should use [Criterium](https://github.com/hugoduncan/criterium) for benchmarking while developing, see below.)
3333

34-
Running the four ”main” solutions via Docker:
34+
You can also build an executable jar and run that:
35+
36+
1. clojure -T:build uber
37+
1. java -jar target/primes.jar '{:variant :boolean-array :warm-up? true}'
38+
39+
To run the four ”main” solutions:
40+
41+
```sh
42+
./build.sh && ./run.sh
43+
```
44+
45+
Using Docker:
3546

3647
```sh
37-
$ docker pull clojure:openjdk-18-tools-deps-1.10.3.1040
3848
$ docker build -t pez-primes-clojure .
3949
$ docker run --rm -it pez-primes-clojure
4050
```
@@ -61,7 +71,7 @@ If you have experience with Clojure: It's just a regular tools/deps project. Sta
6171
If not, I suggest using [Calva](https://calva.io) (yes, partly because I created it 😄):
6272

6373
1. Open the project root in in VS Code.
64-
1. Open `sieve.clj`
74+
1. Open `src/sieve.clj`
6575
1. Issue the command **Calva: Start a Clojure REPL in your Project and Connect (aka Jack-in)**
6676
1. When the REPL has started, issue **Calva: Load current file and its dependencies**
6777

PrimeClojure/solution_3/build.clj

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
(ns build
2+
(:require [clojure.tools.build.api :as b]))
3+
4+
(def class-dir "classes")
5+
(def basis (b/create-basis {:project "deps.edn"}))
6+
7+
(defn clean [_]
8+
(b/delete {:path "target"}))
9+
10+
(defn uber [_]
11+
(clean nil)
12+
(b/copy-dir {:src-dirs ["src"]
13+
:target-dir class-dir})
14+
(b/compile-clj {:basis basis
15+
:src-dirs ["src"]
16+
:class-dir class-dir})
17+
(b/uber {:class-dir class-dir
18+
:uber-file "target/primes.jar"
19+
:basis basis
20+
:main 'sieve}))

PrimeClojure/solution_3/build.sh

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
clojure -T:build uber

PrimeClojure/solution_3/deps.edn

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1-
{:paths ["."]
2-
:deps {org.clojure/clojure {:mvn/version "1.10.3"}
3-
criterium/criterium {:mvn/version "0.4.6"}}}
1+
{:paths ["src"]
2+
:deps {org.clojure/clojure {:mvn/version "1.10.3"}}
3+
:aliases {:benchmark {:extra-deps {criterium/criterium {:mvn/version "0.4.6"}}}
4+
:decompiler {:extra-deps {com.clojure-goes-fast/clj-java-decompiler {:mvn/version "0.3.1"}}}
5+
:profiler {:extra-deps {com.clojure-goes-fast/clj-async-profiler {:mvn/version "0.5.1"}}
6+
:jvm-opts ["-Djdk.attach.allowAttachSelf" "-XX:+UnlockDiagnosticVMOptions" "-XX:+DebugNonSafepoints"]}
7+
:build {:deps {io.github.clojure/tools.build {:git/tag "v0.7.5" :git/sha "34727f7"}}
8+
:ns-default build}}}

PrimeClojure/solution_3/run.sh

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
#!/bin/bash
22

33
RUNS=$(if [ -z "$1" ]; then echo 1; else echo $1; fi)
4-
for ((i=0;i<${RUNS};i++))
4+
for ((i = 0; i < RUNS; i++))
55
do
66
#echo $i
7-
clojure -X sieve/run :variant :vector :warm-up? false
8-
clojure -X sieve/run :variant :vector-transient :warm-up? false
9-
clojure -X sieve/run :variant :bitset :warm-up? true
10-
#clojure -X sieve/run :variant :bitset-shroedinger :warm-up? true
11-
#clojure -X sieve/run :variant :bitset-all :warm-up? false
12-
#clojure -X sieve/run :variant :bitset-pre :warm-up? false
13-
clojure -X sieve/run :variant :boolean-array :warm-up? true
14-
#clojure -X sieve/run :variant :boolean-array-all :warm-up? false
15-
#clojure -X sieve/run :variant :boolean-array-pre :warm-up? false
16-
#clojure -X sieve/run :variant :boolean-array-pre-futures :warm-up? false
17-
#clojure -X sieve/run :variant :boolean-array-to-vector-futures :warm-up? false
7+
java -jar target/primes.jar '{:variant :vector :warm-up? false}'
8+
java -jar target/primes.jar '{:variant :vector-transient :warm-up? false}'
9+
java -jar target/primes.jar '{:variant :bitset :warm-up? true}'
10+
#java -jar target/primes.jar '{:variant :bitset-shroedinger :warm-up? true}'
11+
#java -jar target/primes.jar '{:variant :bitset-all :warm-up? false}'
12+
#java -jar target/primes.jar '{:variant :bitset-pre :warm-up? false}'
13+
java -jar target/primes.jar '{:variant :boolean-array :warm-up? true}'
14+
#java -jar target/primes.jar '{:variant :boolean-array-all :warm-up? false}'
15+
#java -jar target/primes.jar '{:variant :boolean-array-pre :warm-up? false}'
16+
#java -jar target/primes.jar '{:variant :boolean-array-pre-futures :warm-up? false}'
17+
#java -jar target/primes.jar '{:variant :boolean-array-to-vector-futures :warm-up? false}'
1818
done

PrimeClojure/solution_3/sieve.clj PrimeClojure/solution_3/src/sieve.clj

+15-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
(ns sieve
22
"Clojure implementations of The Sieve of Eratosthenes by Peter Strömberg (a.k.a. PEZ)"
3-
(:require [criterium.core :refer [bench quick-bench with-progress-reporting]])
4-
(:import [java.time Instant Duration]))
3+
(:require [clojure.edn])
4+
(:import [java.time Instant Duration])
5+
(:gen-class))
56

67
;; Disable overflow checks on mathematical ops and warn when compiler is unable
78
;; to optimise correctly.
@@ -58,7 +59,8 @@
5859
(loot (sieve 1))
5960
(loot (sieve 10))
6061
(loot (sieve 100))
61-
(time (count (loot (sieve 1000000))))
62+
(time (count (loot (sieve 1000000))))'
63+
(require '[criterium.core :refer [bench quick-bench with-progress-reporting]])
6264
(with-progress-reporting (quick-bench (sieve 1000000))))
6365

6466
(set! *unchecked-math* true)
@@ -96,7 +98,6 @@
9698
(count (loot (sieve-ba 1000)))
9799
(count (loot (sieve-ba 1000000)))
98100
(with-progress-reporting (quick-bench (sieve-ba 1000000)))
99-
(with-progress-reporting (bench (sieve-ba 1000000)))
100101
(time (do (sieve-ba 1000000) nil)))
101102

102103
(defn sieve-bs
@@ -105,17 +106,17 @@
105106
[^long n]
106107
(if (< n 2)
107108
(java.util.BitSet. 0)
108-
(let [half-n (int (bit-shift-right n 1))
109-
primes (doto (java.util.BitSet. n) (.set 0 half-n))
110-
sqrt-n (long (Math/ceil (Math/sqrt (double n))))]
109+
(let [sqrt-n (unchecked-long (Math/ceil (Math/sqrt (double n))))
110+
half-n (unchecked-int (bit-shift-right n 1))
111+
primes (doto (java.util.BitSet. half-n) (.set (unchecked-int 0) half-n))]
111112
(loop [p 3]
112113
(when (< p sqrt-n)
113-
(when (.get primes (unchecked-int (bit-shift-right p (unchecked-int 1))))
114-
(loop [i (bit-shift-right (unchecked-multiply p p) 1)]
114+
(when (.get primes (unchecked-int (bit-shift-right p 1)))
115+
(loop [i (bit-shift-right (* p p) 1)]
115116
(when (< i half-n)
116117
(.clear primes (unchecked-int i))
117-
(recur (unchecked-add-int i p)))))
118-
(recur (unchecked-add-int p 2))))
118+
(recur (+ i p)))))
119+
(recur (+ p 2))))
119120
primes)))
120121

121122
(defn sieve-bs-shroedinger
@@ -543,6 +544,9 @@
543544
(format-results (merge conf (benchmark sieve) {:variant variant})))
544545
(println (format-results (merge conf (benchmark sieve) {:variant variant})))))
545546

547+
(defn -main [& args]
548+
(run (clojure.edn/read-string (first args))))
549+
546550
(comment
547551
(run {:warm-up? true})
548552
(run {:warm-up? false})

0 commit comments

Comments
 (0)