Naked Performance With Clojure

Metosin Oy
Metosin OyMetosin Oy
Naked Performance
(with Clojure)
Tommi Reiman 27.9.2019
ClojuTRE
Programmers waste enormous amounts of
time thinking about, or worrying about, the
speed of noncritical parts of their programs,
and these attempts at efficiency actually
have a strong negative impact when
debugging and maintenance are
considered. We should forget about small
efficiencies, say about 97% of the time:
premature optimization is the root of all
evil. Yet we should not pass up our
opportunities in that critical 3%.
On Performance Optimization
Donald Knuth
Programmers waste enormous amounts of
time thinking about, or worrying about, the
speed of noncritical parts of their programs,
and these attempts at efficiency actually
have a strong negative impact when
debugging and maintenance are
considered. We should forget about small
efficiencies, say about 97% of the time:
premature optimization is the root of all
evil. Yet we should not pass up our
opportunities in that critical 3%.
On Performance Optimization
Donald Knuth
Programmers waste enormous amounts of
time thinking about, or worrying about, the
speed of noncritical parts of their programs,
and these attempts at efficiency actually
have a strong negative impact when
debugging and maintenance are
considered. We should forget about small
efficiencies, say about 97% of the time:
premature optimization is the root of all
evil. Yet we should not pass up our
opportunities in that critical 3%.
On Performance Optimization
Donald Knuth
• The Language
• The Libraries
• The Frameworks
• (The Application)
The 3% in Clojure
TechEmpower Web Framework Benchmarks 2017
5x slower than Java :(
Best we can do?
TechEmpower Web Framework Benchmarks 2019
:)
direct-compilation
fastest java server
reitit-based stack
~600ns budget
1:The LittleThings
Performant Clojure Code
• Reflection, Boxed Math, DynamicVars, …
• Measure and read the source
• Cost of Abstractions
• Cost of Immutability
Naked Performance With Clojure
(defrecord Request [request-method uri])
(import (java.util HashMap))
(let [req1 (hash-map :request-method :get, :uri "/ping")
req2 (array-map :request-method :get, :uri "/ping")
req3 (HashMap. {:request-method :get, :uri "/ping"})
req4 (!"Request :get "/ping")]
#$ 17ns (hash-map)
(cc/quick-bench (:uri req1))
#$ 7ns (array-map)
(cc/quick-bench (:uri req2))
#$ 5ns (mutable-map)
(cc/quick-bench (.get req3 :uri))
#$ 3ns (record)
(cc/quick-bench (:uri req4))
)
#$ 200ns
(cc/quick-bench
(merge {} {}))
#$ 400ns
(cc/quick-bench
(merge {} {} {}))
#$ 600ns
(cc/quick-bench
(merge {} {} {} {}))
#$ 800ns
(cc/quick-bench
(merge {} {} {} {} {}))
#$ 1ϡ &' 200ns
2: Data & Compilers
(def Event
[:map
[:id string?]
[:tags [:set keyword?]]
[:address
[:map
[:street string?]
[:lonlat [:tuple double? double?]]]]])
;; run transformation compiler
(def json->Event
(m/transformer Event mt/json-transformer))
;; 500ns (vs 95µs in spec-tools)
(json->Event some-json)
Naked Performance With Clojure
(r/router
[["/ping"]
["/:user-id/orders"]
["/bulk/:bulk-id"]
["/public()path"]
["/:version/status"]]
{:exception pretty/exception})
Naked Performance With Clojure
Naked Performance With Clojure
Naked Performance With Clojure
(require '[compojure.core :as c])
(defn ping-handler [_]
{:status 200
:headers {"Content-Type" "text/plain"}
:body "pong"})
(def app
(c/context "/api" []
(c/context "/status" []
(c/GET "/ping" [] ping-handler))))
(app {:request-method :get, :uri "/api/status/ping"})
;{:status 200
; :headers {"Content-Type" "text/plain"}
; :body "pong"}
/api
/status
/ping
2.2µs
2.4µs
2.2µs
7.2µs
(require '[reitit.ring :as ring])
(def app
(ring/ring-handler
(ring/router
["/api"
["/status"
["/ping" {:get ping-handler}]]])))
(app {:request-method :get, :uri "/api/status/ping"})
;{:status 200
; :headers {"Content-Type" "text/plain"}
; :body "hello"}
/api/status/ping
126ns
3: Right Algorithms
• SingleStaticPath
• Lookup
• Trie
• Mixed
• Quarantine
• Linear (Brute Force)
Routing Algorithms
Let’s go Crazy
• Create a router with 1000 generated routes, each with 10-20
fragments, generated from clojure.core function names + arguments
• Add a health check route /api/ping as the last route
• Benchmark health check + longest generated path
(!" router (r/routes) (count))
; *+ 1001
(!" router (r/router-name))
; *+ :mixed-router
(r/match-by-path router "/api/ping")
;#Match{:template "/api/ping",
; :data {:name :user/ping},
; :result nil,
; :path-params {},
; :path "/api/ping"}
(r/match-by-path router "/defonce/unchecked-char/rand/unchecked-float/assoc/:val/
remove-all-methods/with-loading-context/boolean-array/alter/:args/char-name-string/
unchecked-negate-int/ex-info/aset/:val/extend-type/:specs/unchecked-multiply-int/
next/chars/prefer-method/:dispatch-val-y/shuffle")
;#Match{:template "/defonce/unchecked-char/rand/,-."
; :data {:name :779},
; :result nil,
; :path-params {:val ":val"
; :args ":args"
; :specs ":specs"
; :dispatch-val-y ":dispatch-val-y"},
; :path "/defonce/unchecked-char/rand/,-."}
health-check: lookup-router (13ns)
longest-path: trie-router (460ns) ~2ϡ
4: Embrace Java
• Undertow/Java
• XNIO, ByteBuffers
• Threads
• java.util.concurrent
• ZeroCopy Requests
• 3.9M text/plain req/sec
(require '[pohjavirta.server :as server])
(defn handler [_]
{:status 200,
:headers {"Content-Type" "text/plain"}
:body "Hello, World!"})
;; create and start the server
(-> handler server/create server/start)
$ wrk -t16 -c16 -d2s http://127.0.0.1:8080
Running 2s test @ http://127.0.0.1:8080
16 threads and 16 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 125.96us 37.69us 1.61ms 94.95%
Req/Sec 7.82k 530.24 8.55k 83.63%
261483 requests in 2.10s, 32.42MB read
Requests/sec: 124548.75
Transfer/sec: 15.44MB
Pohjavirta
partial-
140000
• Writing JSON
• data.json (Clojure)
• Cheshire (Clojure+Java)
• Jsonista (Java + Clojure api)
• Jackson (Java)
Jsonista
(require '[jsonista.core :as j])
(j/write-value-as-string {"hello" 1})
;; => "{"hello":1}"
(j/read-value *1)
;; => {"hello" 1}
~zero-overhead encoding
Naked Performance With Clojure
• Fast Mapping of RDB Data
• Transformation Compiler
• Async, JDBC & jdbc.next
• 450k req/sec onTFB
• 55k req/sec on MacBook
Porsas
(require '[porsas.async :as pa])
(require '[promesa.core :as p])
(def pool
(pa/pool
{:uri "postgresql://localhost:5432/hello_world"
:user "benchmarkdbuser"
:password "benchmarkdbpass"
:size 16}))
(-> (pa/query-one
pool
[“SELECT name from WORLD where id=$1" 1])
(p/chain :name prn))
; #<Promise[~]>
; prints “kikka”
~zero-overhead mapping
Naked Performance With Clojure
What’s Next?
Welcome to the Future!
• GraalVM Profile-Guided
Optimizations (PGO)
• Project Loom: Fibers and
Continuations for the Java
Virtual Machine
• Phoenix Framework
The Libraries
Non-blocking HTTP Server
Data-driven Router
Java-fast JSON Formatter
Java-fast Sync & Async SQL (and jdbc.next)
Fast Interceptors for Clojure/Script
Data-Driven models & validation
Beautiful error messages
Naked Performance With Clojure
Check these out
• ZachTellman - Predictably Fast Clojure
• Tom Crayford - Performance and Lies
• Jonas Östlund - Faster Computations with Generative Expressions
• Thomas Wuerhinger - Maximizing Performance with GraalVM
Naked Performance
• We can create fast libraries and web apps with Clojure
1. Mind the LittleThings (for the 3% of code)
2. Data and Compilers (also better design & DX)
3. Right Algorithms
4. Embrase Java (and the GraalVM)
• Always Measure, http://clojure-goes-fast.com/
Thanks.
Tommi Reiman
tommi@metosin.fi
@ikitommi
https://www.github.com/metosin
talvi.io
1 of 41

Recommended

Why and How to Optimize Your Data Architecture for an Integrated Future by
Why and How to Optimize Your Data Architecture for an Integrated FutureWhy and How to Optimize Your Data Architecture for an Integrated Future
Why and How to Optimize Your Data Architecture for an Integrated FutureMarkus Lanthaler
13.7K views41 slides
개발자를 위한 (블로그) 글쓰기 intro by
개발자를 위한 (블로그) 글쓰기 intro개발자를 위한 (블로그) 글쓰기 intro
개발자를 위한 (블로그) 글쓰기 introSeongyun Byeon
15.6K views136 slides
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가" by
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"용근 권
4.6K views160 slides
TF에서 팀 빌딩까지 9개월의 기록 : 성장하는 조직을 만드는 여정 by
TF에서 팀 빌딩까지 9개월의 기록 : 성장하는 조직을 만드는 여정TF에서 팀 빌딩까지 9개월의 기록 : 성장하는 조직을 만드는 여정
TF에서 팀 빌딩까지 9개월의 기록 : 성장하는 조직을 만드는 여정Seongyun Byeon
14.7K views65 slides
Creating Continuously Up to Date Materialized Aggregates by
Creating Continuously Up to Date Materialized AggregatesCreating Continuously Up to Date Materialized Aggregates
Creating Continuously Up to Date Materialized AggregatesEDB
2K views35 slides
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드 by
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드NAVER Engineering
1.1K views110 slides

More Related Content

What's hot

Incremental Processing on Large Analytical Datasets with Prasanna Rajaperumal... by
Incremental Processing on Large Analytical Datasets with Prasanna Rajaperumal...Incremental Processing on Large Analytical Datasets with Prasanna Rajaperumal...
Incremental Processing on Large Analytical Datasets with Prasanna Rajaperumal...Databricks
3.8K views23 slides
Percona Live 2012PPT: introduction-to-mysql-replication by
Percona Live 2012PPT: introduction-to-mysql-replicationPercona Live 2012PPT: introduction-to-mysql-replication
Percona Live 2012PPT: introduction-to-mysql-replicationmysqlops
5.1K views124 slides
Designing with malli by
Designing with malliDesigning with malli
Designing with malliMetosin Oy
914 views43 slides
Watson Assistant by
Watson AssistantWatson Assistant
Watson AssistantJeanCarl Bisson
1.1K views19 slides
ADRという考えを取り入れてみて by
ADRという考えを取り入れてみてADRという考えを取り入れてみて
ADRという考えを取り入れてみてinfinite_loop
2.9K views49 slides
Full-on Hypermedia APIs with Hydra by
Full-on Hypermedia APIs with HydraFull-on Hypermedia APIs with Hydra
Full-on Hypermedia APIs with HydraMarkus Lanthaler
14.2K views32 slides

What's hot(20)

Incremental Processing on Large Analytical Datasets with Prasanna Rajaperumal... by Databricks
Incremental Processing on Large Analytical Datasets with Prasanna Rajaperumal...Incremental Processing on Large Analytical Datasets with Prasanna Rajaperumal...
Incremental Processing on Large Analytical Datasets with Prasanna Rajaperumal...
Databricks3.8K views
Percona Live 2012PPT: introduction-to-mysql-replication by mysqlops
Percona Live 2012PPT: introduction-to-mysql-replicationPercona Live 2012PPT: introduction-to-mysql-replication
Percona Live 2012PPT: introduction-to-mysql-replication
mysqlops 5.1K views
Designing with malli by Metosin Oy
Designing with malliDesigning with malli
Designing with malli
Metosin Oy914 views
ADRという考えを取り入れてみて by infinite_loop
ADRという考えを取り入れてみてADRという考えを取り入れてみて
ADRという考えを取り入れてみて
infinite_loop2.9K views
Full-on Hypermedia APIs with Hydra by Markus Lanthaler
Full-on Hypermedia APIs with HydraFull-on Hypermedia APIs with Hydra
Full-on Hypermedia APIs with Hydra
Markus Lanthaler14.2K views
Importing Data into Neo4j quickly and easily - StackOverflow by Neo4j
Importing Data into Neo4j quickly and easily - StackOverflowImporting Data into Neo4j quickly and easily - StackOverflow
Importing Data into Neo4j quickly and easily - StackOverflow
Neo4j14.5K views
[143] Modern C++ 무조건 써야 해? by NAVER D2
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?
NAVER D218.6K views
Airflow: Save Tons of Money by Using Deferrable Operators by Kaxil Naik
Airflow: Save Tons of Money by Using Deferrable OperatorsAirflow: Save Tons of Money by Using Deferrable Operators
Airflow: Save Tons of Money by Using Deferrable Operators
Kaxil Naik780 views
Creating Awesome Web APIs is a Breeze by Markus Lanthaler
Creating Awesome Web APIs is a BreezeCreating Awesome Web APIs is a Breeze
Creating Awesome Web APIs is a Breeze
Markus Lanthaler16.4K views
PHP AST 徹底解説 by do_aki
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説
do_aki26.4K views
Introduction to JCR and Apache Jackrabbi by Jukka Zitting
Introduction to JCR and Apache JackrabbiIntroduction to JCR and Apache Jackrabbi
Introduction to JCR and Apache Jackrabbi
Jukka Zitting7.2K views
2021 10-13 i ox query processing by Andrew Lamb
2021 10-13 i ox query processing2021 10-13 i ox query processing
2021 10-13 i ox query processing
Andrew Lamb209 views
Evening out the uneven: dealing with skew in Flink by Flink Forward
Evening out the uneven: dealing with skew in FlinkEvening out the uneven: dealing with skew in Flink
Evening out the uneven: dealing with skew in Flink
Flink Forward2.5K views
Stop Reinventing the Wheel! Use Linked Data to Build Better APIs by Markus Lanthaler
Stop Reinventing the Wheel! Use Linked Data to Build Better APIsStop Reinventing the Wheel! Use Linked Data to Build Better APIs
Stop Reinventing the Wheel! Use Linked Data to Build Better APIs
Markus Lanthaler11.1K views
Event Driven Systems with Spring Boot, Spring Cloud Streams and Kafka by VMware Tanzu
Event Driven Systems with Spring Boot, Spring Cloud Streams and KafkaEvent Driven Systems with Spring Boot, Spring Cloud Streams and Kafka
Event Driven Systems with Spring Boot, Spring Cloud Streams and Kafka
VMware Tanzu1.3K views
MongoDB Performance Tuning by MongoDB
MongoDB Performance TuningMongoDB Performance Tuning
MongoDB Performance Tuning
MongoDB30.5K views
The Web Is Changing — From Strings to Things by Markus Lanthaler
The Web Is Changing — From Strings to ThingsThe Web Is Changing — From Strings to Things
The Web Is Changing — From Strings to Things
Markus Lanthaler12.3K views
엘라스틱서치 실무 가이드_202204.pdf by 한 경만
엘라스틱서치 실무 가이드_202204.pdf엘라스틱서치 실무 가이드_202204.pdf
엘라스틱서치 실무 가이드_202204.pdf
한 경만602 views

Similar to Naked Performance With Clojure

Otimizando seu projeto Rails by
Otimizando seu projeto RailsOtimizando seu projeto Rails
Otimizando seu projeto RailsTiago Albineli Motta
811 views67 slides
Presto anatomy by
Presto anatomyPresto anatomy
Presto anatomyDongmin Yu
5K views50 slides
Azure Cloud Patterns by
Azure Cloud PatternsAzure Cloud Patterns
Azure Cloud PatternsTamir Dresher
948 views56 slides
Non-blocking I/O, Event loops and node.js by
Non-blocking I/O, Event loops and node.jsNon-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.jsMarcus Frödin
22.8K views50 slides
How to Make Norikra Perfect by
How to Make Norikra PerfectHow to Make Norikra Perfect
How to Make Norikra PerfectSATOSHI TAGOMORI
4.7K views29 slides
Dynamic Tracing of your AMP web site by
Dynamic Tracing of your AMP web siteDynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web siteSriram Natarajan
1.3K views17 slides

Similar to Naked Performance With Clojure(20)

Non-blocking I/O, Event loops and node.js by Marcus Frödin
Non-blocking I/O, Event loops and node.jsNon-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.js
Marcus Frödin22.8K views
Dynamic Tracing of your AMP web site by Sriram Natarajan
Dynamic Tracing of your AMP web siteDynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web site
Sriram Natarajan1.3K views
Monitoring with Prometheus by Shiao-An Yuan
Monitoring with PrometheusMonitoring with Prometheus
Monitoring with Prometheus
Shiao-An Yuan5.4K views
Introduction to performance tuning perl web applications by Perrin Harkins
Introduction to performance tuning perl web applicationsIntroduction to performance tuning perl web applications
Introduction to performance tuning perl web applications
Perrin Harkins12.1K views
Calibrate Garbage Collection on the Ground and Run Your Java App in the cloud... by Ana-Maria Mihalceanu
Calibrate Garbage Collection on the Ground and Run Your Java App in the cloud...Calibrate Garbage Collection on the Ground and Run Your Java App in the cloud...
Calibrate Garbage Collection on the Ground and Run Your Java App in the cloud...
Become a Performance Diagnostics Hero by TechWell
Become a Performance Diagnostics HeroBecome a Performance Diagnostics Hero
Become a Performance Diagnostics Hero
TechWell146 views
SE2016 Exotic Valerii Vasylkov "Erlang. Measurements and benefits" by Inhacking
SE2016 Exotic Valerii Vasylkov "Erlang. Measurements and benefits"SE2016 Exotic Valerii Vasylkov "Erlang. Measurements and benefits"
SE2016 Exotic Valerii Vasylkov "Erlang. Measurements and benefits"
Inhacking119 views
Performance and how to measure it - ProgSCon London 2016 by Matt Warren
Performance and how to measure it - ProgSCon London 2016Performance and how to measure it - ProgSCon London 2016
Performance and how to measure it - ProgSCon London 2016
Matt Warren769 views
Building and Scaling Node.js Applications by Ohad Kravchick
Building and Scaling Node.js ApplicationsBuilding and Scaling Node.js Applications
Building and Scaling Node.js Applications
Ohad Kravchick1.7K views
HBaseCon 2013: How (and Why) Phoenix Puts the SQL Back into NoSQL by Cloudera, Inc.
HBaseCon 2013: How (and Why) Phoenix Puts the SQL Back into NoSQLHBaseCon 2013: How (and Why) Phoenix Puts the SQL Back into NoSQL
HBaseCon 2013: How (and Why) Phoenix Puts the SQL Back into NoSQL
Cloudera, Inc.5.3K views
Performance Optimization of Rails Applications by Serge Smetana
Performance Optimization of Rails ApplicationsPerformance Optimization of Rails Applications
Performance Optimization of Rails Applications
Serge Smetana8.8K views
DjangoCon 2010 Scaling Disqus by zeeg
DjangoCon 2010 Scaling DisqusDjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling Disqus
zeeg32.6K views
Pinot: Realtime OLAP for 530 Million Users - Sigmod 2018 by Seunghyun Lee
Pinot: Realtime OLAP for 530 Million Users - Sigmod 2018Pinot: Realtime OLAP for 530 Million Users - Sigmod 2018
Pinot: Realtime OLAP for 530 Million Users - Sigmod 2018
Seunghyun Lee3.1K views

More from Metosin Oy

Navigating container technology for enhanced security by Niklas Saari by
Navigating container technology for enhanced security by Niklas SaariNavigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas SaariMetosin Oy
14 views34 slides
Where is Technical Debt? by
Where is Technical Debt?Where is Technical Debt?
Where is Technical Debt?Metosin Oy
25 views21 slides
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra... by
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...Metosin Oy
72 views36 slides
Serverless Clojure and ML prototyping: an experience report by
Serverless Clojure and ML prototyping: an experience reportServerless Clojure and ML prototyping: an experience report
Serverless Clojure and ML prototyping: an experience reportMetosin Oy
97 views27 slides
Malli: inside data-driven schemas by
Malli: inside data-driven schemasMalli: inside data-driven schemas
Malli: inside data-driven schemasMetosin Oy
1K views56 slides
Reitit - Clojure/North 2019 by
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Metosin Oy
4.3K views76 slides

More from Metosin Oy(19)

Navigating container technology for enhanced security by Niklas Saari by Metosin Oy
Navigating container technology for enhanced security by Niklas SaariNavigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas Saari
Metosin Oy14 views
Where is Technical Debt? by Metosin Oy
Where is Technical Debt?Where is Technical Debt?
Where is Technical Debt?
Metosin Oy25 views
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra... by Metosin Oy
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
Metosin Oy72 views
Serverless Clojure and ML prototyping: an experience report by Metosin Oy
Serverless Clojure and ML prototyping: an experience reportServerless Clojure and ML prototyping: an experience report
Serverless Clojure and ML prototyping: an experience report
Metosin Oy97 views
Malli: inside data-driven schemas by Metosin Oy
Malli: inside data-driven schemasMalli: inside data-driven schemas
Malli: inside data-driven schemas
Metosin Oy1K views
Reitit - Clojure/North 2019 by Metosin Oy
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
Metosin Oy4.3K views
Fun with errors? - Clojure Finland Meetup 26.3.2019 Tampere by Metosin Oy
Fun with errors? - Clojure Finland Meetup 26.3.2019 TampereFun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
Fun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
Metosin Oy1.4K views
Clojutre Real Life (2012 ClojuTRE Retro Edition) by Metosin Oy
Clojutre Real Life (2012 ClojuTRE Retro Edition)Clojutre Real Life (2012 ClojuTRE Retro Edition)
Clojutre Real Life (2012 ClojuTRE Retro Edition)
Metosin Oy283 views
The Ancient Art of Data-Driven - reitit, the library - by Metosin Oy
The Ancient Art of Data-Driven - reitit, the library - The Ancient Art of Data-Driven - reitit, the library -
The Ancient Art of Data-Driven - reitit, the library -
Metosin Oy348 views
Craft Beer & Clojure by Metosin Oy
Craft Beer & ClojureCraft Beer & Clojure
Craft Beer & Clojure
Metosin Oy403 views
Performance and Abstractions by Metosin Oy
Performance and AbstractionsPerformance and Abstractions
Performance and Abstractions
Metosin Oy1.1K views
ClojuTRE2016 Opening slides by Metosin Oy
ClojuTRE2016 Opening slidesClojuTRE2016 Opening slides
ClojuTRE2016 Opening slides
Metosin Oy293 views
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016 by Metosin Oy
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
Metosin Oy2.1K views
ClojuTRE - a (very) brief history by Metosin Oy
ClojuTRE - a (very) brief historyClojuTRE - a (very) brief history
ClojuTRE - a (very) brief history
Metosin Oy254 views
Wieldy remote apis with Kekkonen - ClojureD 2016 by Metosin Oy
Wieldy remote apis with Kekkonen - ClojureD 2016Wieldy remote apis with Kekkonen - ClojureD 2016
Wieldy remote apis with Kekkonen - ClojureD 2016
Metosin Oy1.3K views
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome by Metosin Oy
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesomeClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
Metosin Oy1.5K views
Clojure in real life 17.10.2014 by Metosin Oy
Clojure in real life 17.10.2014Clojure in real life 17.10.2014
Clojure in real life 17.10.2014
Metosin Oy3.6K views
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome by Metosin Oy
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesomeEuroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Metosin Oy5K views
Swaggered web apis in Clojure by Metosin Oy
Swaggered web apis in ClojureSwaggered web apis in Clojure
Swaggered web apis in Clojure
Metosin Oy5.2K views

Recently uploaded

"Running students' code in isolation. The hard way", Yurii Holiuk by
"Running students' code in isolation. The hard way", Yurii Holiuk "Running students' code in isolation. The hard way", Yurii Holiuk
"Running students' code in isolation. The hard way", Yurii Holiuk Fwdays
17 views34 slides
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas... by
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...Bernd Ruecker
40 views69 slides
Info Session November 2023.pdf by
Info Session November 2023.pdfInfo Session November 2023.pdf
Info Session November 2023.pdfAleksandraKoprivica4
13 views15 slides
Scaling Knowledge Graph Architectures with AI by
Scaling Knowledge Graph Architectures with AIScaling Knowledge Graph Architectures with AI
Scaling Knowledge Graph Architectures with AIEnterprise Knowledge
38 views15 slides
STPI OctaNE CoE Brochure.pdf by
STPI OctaNE CoE Brochure.pdfSTPI OctaNE CoE Brochure.pdf
STPI OctaNE CoE Brochure.pdfmadhurjyapb
14 views1 slide
SUPPLIER SOURCING.pptx by
SUPPLIER SOURCING.pptxSUPPLIER SOURCING.pptx
SUPPLIER SOURCING.pptxangelicacueva6
16 views1 slide

Recently uploaded(20)

"Running students' code in isolation. The hard way", Yurii Holiuk by Fwdays
"Running students' code in isolation. The hard way", Yurii Holiuk "Running students' code in isolation. The hard way", Yurii Holiuk
"Running students' code in isolation. The hard way", Yurii Holiuk
Fwdays17 views
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas... by Bernd Ruecker
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...
Bernd Ruecker40 views
STPI OctaNE CoE Brochure.pdf by madhurjyapb
STPI OctaNE CoE Brochure.pdfSTPI OctaNE CoE Brochure.pdf
STPI OctaNE CoE Brochure.pdf
madhurjyapb14 views
Igniting Next Level Productivity with AI-Infused Data Integration Workflows by Safe Software
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Safe Software280 views
Unit 1_Lecture 2_Physical Design of IoT.pdf by StephenTec
Unit 1_Lecture 2_Physical Design of IoT.pdfUnit 1_Lecture 2_Physical Design of IoT.pdf
Unit 1_Lecture 2_Physical Design of IoT.pdf
StephenTec12 views
PharoJS - Zürich Smalltalk Group Meetup November 2023 by Noury Bouraqadi
PharoJS - Zürich Smalltalk Group Meetup November 2023PharoJS - Zürich Smalltalk Group Meetup November 2023
PharoJS - Zürich Smalltalk Group Meetup November 2023
Noury Bouraqadi132 views
Future of AR - Facebook Presentation by ssuserb54b561
Future of AR - Facebook PresentationFuture of AR - Facebook Presentation
Future of AR - Facebook Presentation
ssuserb54b56115 views
Five Things You SHOULD Know About Postman by Postman
Five Things You SHOULD Know About PostmanFive Things You SHOULD Know About Postman
Five Things You SHOULD Know About Postman
Postman36 views
Business Analyst Series 2023 - Week 3 Session 5 by DianaGray10
Business Analyst Series 2023 -  Week 3 Session 5Business Analyst Series 2023 -  Week 3 Session 5
Business Analyst Series 2023 - Week 3 Session 5
DianaGray10300 views

Naked Performance With Clojure

  • 1. Naked Performance (with Clojure) Tommi Reiman 27.9.2019 ClojuTRE
  • 2. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. On Performance Optimization Donald Knuth
  • 3. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. On Performance Optimization Donald Knuth
  • 4. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. On Performance Optimization Donald Knuth
  • 5. • The Language • The Libraries • The Frameworks • (The Application) The 3% in Clojure
  • 6. TechEmpower Web Framework Benchmarks 2017 5x slower than Java :( Best we can do?
  • 7. TechEmpower Web Framework Benchmarks 2019 :) direct-compilation fastest java server reitit-based stack ~600ns budget
  • 9. Performant Clojure Code • Reflection, Boxed Math, DynamicVars, … • Measure and read the source • Cost of Abstractions • Cost of Immutability
  • 11. (defrecord Request [request-method uri]) (import (java.util HashMap)) (let [req1 (hash-map :request-method :get, :uri "/ping") req2 (array-map :request-method :get, :uri "/ping") req3 (HashMap. {:request-method :get, :uri "/ping"}) req4 (!"Request :get "/ping")] #$ 17ns (hash-map) (cc/quick-bench (:uri req1)) #$ 7ns (array-map) (cc/quick-bench (:uri req2)) #$ 5ns (mutable-map) (cc/quick-bench (.get req3 :uri)) #$ 3ns (record) (cc/quick-bench (:uri req4)) )
  • 12. #$ 200ns (cc/quick-bench (merge {} {})) #$ 400ns (cc/quick-bench (merge {} {} {})) #$ 600ns (cc/quick-bench (merge {} {} {} {})) #$ 800ns (cc/quick-bench (merge {} {} {} {} {})) #$ 1ϡ &' 200ns
  • 13. 2: Data & Compilers
  • 14. (def Event [:map [:id string?] [:tags [:set keyword?]] [:address [:map [:street string?] [:lonlat [:tuple double? double?]]]]]) ;; run transformation compiler (def json->Event (m/transformer Event mt/json-transformer)) ;; 500ns (vs 95µs in spec-tools) (json->Event some-json)
  • 20. (require '[compojure.core :as c]) (defn ping-handler [_] {:status 200 :headers {"Content-Type" "text/plain"} :body "pong"}) (def app (c/context "/api" [] (c/context "/status" [] (c/GET "/ping" [] ping-handler)))) (app {:request-method :get, :uri "/api/status/ping"}) ;{:status 200 ; :headers {"Content-Type" "text/plain"} ; :body "pong"}
  • 22. (require '[reitit.ring :as ring]) (def app (ring/ring-handler (ring/router ["/api" ["/status" ["/ping" {:get ping-handler}]]]))) (app {:request-method :get, :uri "/api/status/ping"}) ;{:status 200 ; :headers {"Content-Type" "text/plain"} ; :body "hello"}
  • 25. • SingleStaticPath • Lookup • Trie • Mixed • Quarantine • Linear (Brute Force) Routing Algorithms
  • 26. Let’s go Crazy • Create a router with 1000 generated routes, each with 10-20 fragments, generated from clojure.core function names + arguments • Add a health check route /api/ping as the last route • Benchmark health check + longest generated path
  • 27. (!" router (r/routes) (count)) ; *+ 1001 (!" router (r/router-name)) ; *+ :mixed-router (r/match-by-path router "/api/ping") ;#Match{:template "/api/ping", ; :data {:name :user/ping}, ; :result nil, ; :path-params {}, ; :path "/api/ping"} (r/match-by-path router "/defonce/unchecked-char/rand/unchecked-float/assoc/:val/ remove-all-methods/with-loading-context/boolean-array/alter/:args/char-name-string/ unchecked-negate-int/ex-info/aset/:val/extend-type/:specs/unchecked-multiply-int/ next/chars/prefer-method/:dispatch-val-y/shuffle") ;#Match{:template "/defonce/unchecked-char/rand/,-." ; :data {:name :779}, ; :result nil, ; :path-params {:val ":val" ; :args ":args" ; :specs ":specs" ; :dispatch-val-y ":dispatch-val-y"}, ; :path "/defonce/unchecked-char/rand/,-."}
  • 30. • Undertow/Java • XNIO, ByteBuffers • Threads • java.util.concurrent • ZeroCopy Requests • 3.9M text/plain req/sec (require '[pohjavirta.server :as server]) (defn handler [_] {:status 200, :headers {"Content-Type" "text/plain"} :body "Hello, World!"}) ;; create and start the server (-> handler server/create server/start) $ wrk -t16 -c16 -d2s http://127.0.0.1:8080 Running 2s test @ http://127.0.0.1:8080 16 threads and 16 connections Thread Stats Avg Stdev Max +/- Stdev Latency 125.96us 37.69us 1.61ms 94.95% Req/Sec 7.82k 530.24 8.55k 83.63% 261483 requests in 2.10s, 32.42MB read Requests/sec: 124548.75 Transfer/sec: 15.44MB Pohjavirta partial- 140000
  • 31. • Writing JSON • data.json (Clojure) • Cheshire (Clojure+Java) • Jsonista (Java + Clojure api) • Jackson (Java) Jsonista (require '[jsonista.core :as j]) (j/write-value-as-string {"hello" 1}) ;; => "{"hello":1}" (j/read-value *1) ;; => {"hello" 1} ~zero-overhead encoding
  • 33. • Fast Mapping of RDB Data • Transformation Compiler • Async, JDBC & jdbc.next • 450k req/sec onTFB • 55k req/sec on MacBook Porsas (require '[porsas.async :as pa]) (require '[promesa.core :as p]) (def pool (pa/pool {:uri "postgresql://localhost:5432/hello_world" :user "benchmarkdbuser" :password "benchmarkdbpass" :size 16})) (-> (pa/query-one pool [“SELECT name from WORLD where id=$1" 1]) (p/chain :name prn)) ; #<Promise[~]> ; prints “kikka” ~zero-overhead mapping
  • 36. Welcome to the Future! • GraalVM Profile-Guided Optimizations (PGO) • Project Loom: Fibers and Continuations for the Java Virtual Machine • Phoenix Framework
  • 37. The Libraries Non-blocking HTTP Server Data-driven Router Java-fast JSON Formatter Java-fast Sync & Async SQL (and jdbc.next) Fast Interceptors for Clojure/Script Data-Driven models & validation Beautiful error messages
  • 39. Check these out • ZachTellman - Predictably Fast Clojure • Tom Crayford - Performance and Lies • Jonas Östlund - Faster Computations with Generative Expressions • Thomas Wuerhinger - Maximizing Performance with GraalVM
  • 40. Naked Performance • We can create fast libraries and web apps with Clojure 1. Mind the LittleThings (for the 3% of code) 2. Data and Compilers (also better design & DX) 3. Right Algorithms 4. Embrase Java (and the GraalVM) • Always Measure, http://clojure-goes-fast.com/