SlideShare uma empresa Scribd logo
1 de 82
Baixar para ler offline
PREDICTABLY FAST	

CLOJURE
ZachTellman	

@ztellman
(nth s 2)
(nth s 2)
(.nth ^clojure.lang.Indexed s 2)
(nth s 2)
(java.lang.reflect.Array/get s 2)
(.nth ^clojure.lang.Indexed s 2)
(nth s 2)
(java.lang.reflect.Array/get s 2)
(.get ^java.util.RandomAccess s 2)
(.nth ^clojure.lang.Indexed s 2)
(nth s 2)
(java.lang.reflect.Array/get s 2)
(.get ^java.util.RandomAccess s 2)
(.nth ^clojure.lang.Indexed s 2)
(Character. (.charAt ^CharSequence s 2))
(nth s 2)
(java.lang.reflect.Array/get s 2)
(.get ^java.util.RandomAccess s 2)
(.nth ^clojure.lang.Indexed s 2)
(Character. (.charAt ^CharSequence s 2))
(first (next (next s)))
REFERENTIAL	

TRANSPARENCY
(+ 1 1)
2
~
REFERENTIAL	

TRANSPARENCY
(f x)
((memoize f) x)
~
REFERENTIAL	

TRANSPARENCY
(map f s)
(doall (map f s))
~
REFERENTIAL	

TRANSPARENCY
(map f s)
(pmap f s)
~
(map f s)
(map
(fn [x]
(Thread/sleep 1000)
(f x))
s)
?
REFERENTIAL
TRANSPARENCY
ASSUMES	

INFINITE RESOURCES
REFERENTIAL
TRANSPARENCY
IS	

CONTEXTUAL
THE UTILITY OF	

ANY ABSTRACTION	

IS	

CONTEXTUAL
CORRECTNESS
IS	

CONTEXTUAL
PREDICTABLY FAST	

CLOJURE
ZachTellman	

@ztellman
LOOKING DEEP INTO	

THE ABYSS
ZachTellman	

@ztellman
LOOKING DEEP INTO	

THE ABYSS,	

USING CLOJURE
ZachTellman	

@ztellman
WHATTO DO WHEN	

YOUR ASSUMPTIONS	

COME CRASHING DOWN	

AROUNDYOU
ZachTellman	

@ztellman
MY RESPONSIBILITIES
• 100k requests/sec, at peak	

• intake of terabytes of compressed data per day	

• eight hours of uninterrupted sleep
MY RESPONSIBILITIES
• looking deep into the abyss, using Clojure	

• waiting for my assumptions to come crashing
down around me
(count s)
(defn count
{:inline (fn [x]
`(. clojure.lang.RT (count ~x)))}
[coll]
(clojure.lang.RT/count coll))
public static int count(Object o) {
if(o instanceof Counted)
return ((Counted) o).count();
return countFrom(Util.ret1(o, o = null));
}
(let [v [1 2 3]]
(quick-bench
(count v)))
(let [v [1 2 3]]
(quick-bench
(.count ^Counted v)))
~10 ns
~5 ns
(defn matching-index [offset ks prefix]
(let [cnt-ks (- (count ks) offset)
cnt-prefix (Array/getLength prefix)
cnt (Math/min cnt-ks cnt-prefix)]
(loop [idx 0]
(if (== cnt idx)
(+ offset idx)
(if (= (nth ks (+ offset idx))
(aget prefix idx))
(recur (inc idx))
(+ offset idx))))))
~200 ns
(defn matching-index [offset ks prefix]
(let [cnt-ks (- (.count ^Counted ks) offset)
cnt-prefix (Array/getLength prefix)
cnt (Math/min cnt-ks cnt-prefix)]
(loop [idx 0]
(if (== cnt idx)
(+ offset idx)
(if (= (nth ks (+ offset idx))
(aget prefix idx))
(recur (inc idx))
(+ offset idx))))))
~100 ns
PERFORMANCE 	

IS	

ALMOST NEVER
THE 	

SUM OF ITS PARTS
WHY IS IT	

SLOWER THAN JAVA?
THE ETERNAL QUESTION:
(+ 2 1)
!
(+ (Long. 2) 1)
!
(+ (/ 3 2) (/ 3 2))
!
(+ 2 (BigInteger. 1))
NO.DISASSEMBLE
> (use 'no.disassemble)
nil
!
> (defn log [x] (Math/log x))
#’log
!
> (println (disassemble log))
public final class user$log extends clojure.lang.AFunction {
public static {};
...
public user$log();
...
public java.lang.Object invoke(java.lang.Object x);
...
}
public java.lang.Object invoke(java.lang.Object x);
0 aload_1 [x]
1 aconst_null
2 astore_1 [x]
3 checkcast java.lang.Number
6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double
9 invokestatic java.lang.Math.log(double) : double
12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double
15 areturn
(fn [x] (Math/log x))
public java.lang.Object invoke(java.lang.Object x);
0 aload_1 [x]
1 aconst_null
2 astore_1 [x]
3 checkcast java.lang.Number
6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double
9 invokestatic java.lang.Math.log(double) : double
12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double
15 areturn
(fn [x] (Math/log x))
public java.lang.Object invoke(java.lang.Object x);
0 aload_1 [x]
1 aconst_null
2 astore_1 [x]
3 checkcast java.lang.Number
6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double
9 invokestatic java.lang.Math.log(double) : double
12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double
15 areturn
(fn [x] (Math/log x))
public java.lang.Object invoke(java.lang.Object x);
0 aload_1 [x]
1 aconst_null
2 astore_1 [x]
3 checkcast java.lang.Number
6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double
9 invokestatic java.lang.Math.log(double) : double
12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double
15 areturn
(fn [x] (Math/log x))
public java.lang.Object invoke(java.lang.Object x);
0 aload_1 [x]
1 aconst_null
2 astore_1 [x]
3 checkcast java.lang.Number
6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double
9 invokestatic java.lang.Math.log(double) : double
12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double
15 areturn
(fn [x] (Math/log x))
(fn ^double [^double x] (Math/log x))
public java.lang.Object invoke(java.lang.Object arg0);
0 aload_0
1 aload_1
2 checkcast java.lang.Number
5 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double
8 invokeinterface clojure.lang.IFn$DD.invokePrim(double) : double
13 new java.lang.Double
16 dup_x2
17 dup_x2
18 pop
19 invokespecial java.lang.Double(double)
22 areturn
(fn ^double [^double x] (Math/log x))
public final double invokePrim(double x);
0 dload_1 [x]
1 invokestatic java.lang.Math.log(double) : double
4 dreturn
(fn [x y] (Math/min x y))
public java.lang.Object invoke(java.lang.Object x, java.lang.Object y);
0 ldc <String "java.lang.Math">
2 invokestatic java.lang.Class.forName(java.lang.String) : java.lang.Class
5 ldc <String "min">
7 iconst_2
8 anewarray java.lang.Object
11 dup
12 iconst_0
13 aload_1 [x]
14 aconst_null
15 astore_1 [x]
16 aastore
17 dup
18 iconst_1
19 aload_2 [y]
20 aconst_null
21 astore_2
22 aastore
23 invokestatic clojure.lang.Reflector.invokeStaticMethod …
26 areturn
(fn [x y] (+ x y))
public java.lang.Object invoke(java.lang.Object x, java.lang.Object y);
0 aload_1 [x]
1 aconst_null
2 astore_1 [x]
3 aload_2 [y]
4 aconst_null
5 astore_2 [y]
6 invokestatic clojure.lang.Numbers.add(java.lang.Object, java.lang.Object) …
9 areturn
static public Number add(Object x, Object y){
return ops(x).combine(ops(y)).add((Number)x, (Number)y);
}
 
class LongOps {
final public Number add(Number x, Number y){
return num(Numbers.add(x.longValue(),y.longValue()));
}
}
 
static public long add(long x, long y){
long ret = x + y;
if ((ret ^ x) < 0 && (ret ^ y) < 0)
return throwIntOverflow();
return ret;
}
(fn [x y] (+ x y))
(fn [^long x ^long y] (+ x y))
public final java.lang.Object invokePrim(long x, long arg1);
0 lload_1 [x]
1 lload_3
2 invokestatic clojure.lang.Numbers.add(long, long) : long
5 invokestatic clojure.lang.Numbers.num(long) : java.lang.Number
8 areturn
(fn ^long [^long x ^long x] (+ x y))
public final long invokePrim(long x, long arg1);
0 lload_1 [x]
1 lload_3
2 invokestatic clojure.lang.Numbers.add(long, long) : long
5 lreturn
 
(fn ^long [^long x ^long y] (unchecked-add x y))
public final long invokePrim(long x, long arg1);
0 lload_1 [x]
1 lload_3
2 ladd
5 lreturn
 
(fn ^long [^long x ^long y] (unchecked-add x y))
AS FAST AS JAVA!
public final long invokePrim(long x, long arg1);
0 lload_1 [x]
1 lload_3
2 ladd
5 lreturn
 
(fn [x y] (unchecked-add x y))
public java.lang.Object invoke(java.lang.Object x, java.lang.Object y);
0 aload_1 [x]
1 aconst_null
2 astore_1 [x]
3 aload_2 [y]
4 aconst_null
5 astore_2 [y]
6 invokestatic clojure.lang.Numbers.unchecked_add(java.lang.Object, …
9 areturn
AND SO…
public class Primitives {
!
…
!
public static long add(long a, long b) {
return a + b;
}
 
public static double add(double a, double b) {
return a + b;
}
!
…
!
}
> (require '[primitive-math :as p])
nil
!
> (macroexpand '(p/+ x y))
(. primitive_math.Primitives add x y)
(fn ^long [^long x ^long y] (p/+ x y))
public final long invokePrim(long x, long arg1);
0 lload_1 [x]
1 lload_3
2 invokestatic primitive_math.Primitives.add(long, long) : long
5 lreturn
> (set! *warn-on-reflection* true)
true
!
> (fn [x y] (unchecked-add x y))
#<...>
!
> (fn [x y] (p/+ x y))
Reflection warning - call to add can't be resolved.
#<...>
• does not supplant Clojure’s numerics	

• invariants via feedback when they aren’t
satisfied	

• using Java isn’t cheating
INTHE BEGINNING,	

THERE WASTHE 	

INPUT STREAM
AND SO…
(quick-bench
(.getBytes
"a reasonably long string"))
(let [f (memoize identity)]
(quick-bench
(f 1)))
~60 ns
~100 ns
(defn memoize
[f]
(let [mem (atom {})]
(fn [& args]
(if-let [e (find @mem args)]
(val e)
(let [ret (apply f args)]
(swap! mem assoc args ret)
ret)))))
{} or (array-map)
(hash-map)
• up to eight calls to .equiv()
A LOOKUP
• one call to .hasheq(), approx. one call to .equiv()
if(obj instanceof IPersistentVector) {
Collection ma = (Collection) obj;
if (ma.size() != v.count())
return false;
for(Iterator i1 = ((List) v).iterator(),
i2 = ma.iterator();
i1.hasNext();) {
if (!Util.equiv(i1.next(), i2.next()))
return false;
}
return true;
}
AND SO…
(deftype Tuple0 [])
!
(deftype Tuple1 [a])
!
(deftype Tuple2 [a b])
!
(deftype Tuple3 [a b c])
!
…
(if (instance? ~name x##)
~(if (zero? cardinality)
true
`(and
~@(map
(fn [f]
`(Util/equiv ~f (. ~other ~f)))
fields)))
…)
(let [v [1 2 3]]
(quick-bench
(nth v 0)))
(let [v [1 2 3]]
(quick-bench
(first v)))
~5 ns
~50 ns
(let [t (tuple 1 2 3)]
(quick-bench
(nth t 0)))
(let [t (tuple 1 2 3)]
(quick-bench
(first t)))
~5 ns
~5 ns
• if you can, do the hard work once	

• if you don’t control the context, assume
every bit matters
• if you can, do the hard work at compile-time	

• the tools for library-sized macros are a bit
lacking right now
I WORK WITH 	

THIS GUY
(he is programming)
AND SO…
MUTABILITY!
(let-mutable [x 0]
(dotimes [_ 100]
(set! x (inc x)))
x)
(let [x (LongContainer. 0)]
(dotimes [_ 100]
(.set x (inc (.get x))))
(.get x))
(let-mutable [x 1]
(fn [] x))
(let [x (LongContainer. 1)]
(let [x (.get x)]
(fn [] x)))
• Clojure’s general solutions are fairly
pessimistic, and assume few invariants	

• try creating a more optimistic context
YOU DON’T HAVETO DO	

WHAT HE DID
AND SO…
SOME FINALTHOUGHTS
• be curious about the tools you use	

• if you’re going for a bounded solution, describe the
boundaries fully	

• if you’re going for a general solution, make sure it’s
actually general
QUESTIONS?

Mais conteúdo relacionado

Mais procurados

Java 8 Puzzlers [as presented at OSCON 2016]
Java 8 Puzzlers [as presented at  OSCON 2016]Java 8 Puzzlers [as presented at  OSCON 2016]
Java 8 Puzzlers [as presented at OSCON 2016]Baruch Sadogursky
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldBTI360
 
JavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java DevelopersJavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java DevelopersJan Kronquist
 
Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)Will Kurt
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecLoïc Descotte
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidJordi Gerona
 
QA Auotmation Java programs,theory
QA Auotmation Java programs,theory QA Auotmation Java programs,theory
QA Auotmation Java programs,theory archana singh
 
Kotlin collections
Kotlin collectionsKotlin collections
Kotlin collectionsMyeongin Woo
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Leonardo Borges
 
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorFedor Lavrentyev
 
Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner codeMite Mitreski
 
Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015Leonardo Borges
 

Mais procurados (20)

Java 8 Puzzlers [as presented at OSCON 2016]
Java 8 Puzzlers [as presented at  OSCON 2016]Java 8 Puzzlers [as presented at  OSCON 2016]
Java 8 Puzzlers [as presented at OSCON 2016]
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
JavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java DevelopersJavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java Developers
 
Clojure class
Clojure classClojure class
Clojure class
 
Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)
 
Why Learn Python?
Why Learn Python?Why Learn Python?
Why Learn Python?
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar Prokopec
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & Android
 
QA Auotmation Java programs,theory
QA Auotmation Java programs,theory QA Auotmation Java programs,theory
QA Auotmation Java programs,theory
 
Kotlin collections
Kotlin collectionsKotlin collections
Kotlin collections
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012
 
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner code
 
Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015
 
Java Cheat Sheet
Java Cheat SheetJava Cheat Sheet
Java Cheat Sheet
 
Lezione03
Lezione03Lezione03
Lezione03
 
Kotlin, why?
Kotlin, why?Kotlin, why?
Kotlin, why?
 
Sneaking inside Kotlin features
Sneaking inside Kotlin featuresSneaking inside Kotlin features
Sneaking inside Kotlin features
 
Google guava
Google guavaGoogle guava
Google guava
 

Semelhante a Predictably

(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)Jacek Laskowski
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talkJohn Stevenson
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
JDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation streamJDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation stream
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation streamRuslan Shevchenko
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghStuart Roebuck
 
RxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниRxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниStfalcon Meetups
 
Clojure made really really simple
Clojure made really really simpleClojure made really really simple
Clojure made really really simpleJohn Stevenson
 
여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala LanguageAshal aka JOKER
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Beauty and the beast - Haskell on JVM
Beauty and the beast  - Haskell on JVMBeauty and the beast  - Haskell on JVM
Beauty and the beast - Haskell on JVMJarek Ratajski
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Introthnetos
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Baruch Sadogursky
 
(first '(Clojure.))
(first '(Clojure.))(first '(Clojure.))
(first '(Clojure.))niklal
 
Macrobrew: Clojure macros distilled
Macrobrew: Clojure macros distilledMacrobrew: Clojure macros distilled
Macrobrew: Clojure macros distilledabhinavomprakash10
 

Semelhante a Predictably (20)

(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)
 
Hw09 Hadoop + Clojure
Hw09   Hadoop + ClojureHw09   Hadoop + Clojure
Hw09 Hadoop + Clojure
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talk
 
Hadoop + Clojure
Hadoop + ClojureHadoop + Clojure
Hadoop + Clojure
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
JDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation streamJDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation stream
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
 
Ecma script 5
Ecma script 5Ecma script 5
Ecma script 5
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
RxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниRxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камни
 
Clojure made really really simple
Clojure made really really simpleClojure made really really simple
Clojure made really really simple
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Scala coated JVM
Scala coated JVMScala coated JVM
Scala coated JVM
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Beauty and the beast - Haskell on JVM
Beauty and the beast  - Haskell on JVMBeauty and the beast  - Haskell on JVM
Beauty and the beast - Haskell on JVM
 
Eta
EtaEta
Eta
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
 
(first '(Clojure.))
(first '(Clojure.))(first '(Clojure.))
(first '(Clojure.))
 
Macrobrew: Clojure macros distilled
Macrobrew: Clojure macros distilledMacrobrew: Clojure macros distilled
Macrobrew: Clojure macros distilled
 

Último

%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024VictoriaMetrics
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburgmasabamasaba
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxalwaysnagaraju26
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...masabamasaba
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 

Último (20)

%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...
Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...
Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 

Predictably

  • 3. (nth s 2) (.nth ^clojure.lang.Indexed s 2)
  • 4. (nth s 2) (java.lang.reflect.Array/get s 2) (.nth ^clojure.lang.Indexed s 2)
  • 5. (nth s 2) (java.lang.reflect.Array/get s 2) (.get ^java.util.RandomAccess s 2) (.nth ^clojure.lang.Indexed s 2)
  • 6. (nth s 2) (java.lang.reflect.Array/get s 2) (.get ^java.util.RandomAccess s 2) (.nth ^clojure.lang.Indexed s 2) (Character. (.charAt ^CharSequence s 2))
  • 7. (nth s 2) (java.lang.reflect.Array/get s 2) (.get ^java.util.RandomAccess s 2) (.nth ^clojure.lang.Indexed s 2) (Character. (.charAt ^CharSequence s 2)) (first (next (next s)))
  • 12. (map f s) (map (fn [x] (Thread/sleep 1000) (f x)) s) ?
  • 15. THE UTILITY OF ANY ABSTRACTION IS CONTEXTUAL
  • 18. LOOKING DEEP INTO THE ABYSS ZachTellman @ztellman
  • 19. LOOKING DEEP INTO THE ABYSS, USING CLOJURE ZachTellman @ztellman
  • 20. WHATTO DO WHEN YOUR ASSUMPTIONS COME CRASHING DOWN AROUNDYOU ZachTellman @ztellman
  • 21.
  • 22.
  • 23. MY RESPONSIBILITIES • 100k requests/sec, at peak • intake of terabytes of compressed data per day • eight hours of uninterrupted sleep
  • 24. MY RESPONSIBILITIES • looking deep into the abyss, using Clojure • waiting for my assumptions to come crashing down around me
  • 26. (defn count {:inline (fn [x] `(. clojure.lang.RT (count ~x)))} [coll] (clojure.lang.RT/count coll))
  • 27. public static int count(Object o) { if(o instanceof Counted) return ((Counted) o).count(); return countFrom(Util.ret1(o, o = null)); }
  • 28. (let [v [1 2 3]] (quick-bench (count v))) (let [v [1 2 3]] (quick-bench (.count ^Counted v))) ~10 ns ~5 ns
  • 29. (defn matching-index [offset ks prefix] (let [cnt-ks (- (count ks) offset) cnt-prefix (Array/getLength prefix) cnt (Math/min cnt-ks cnt-prefix)] (loop [idx 0] (if (== cnt idx) (+ offset idx) (if (= (nth ks (+ offset idx)) (aget prefix idx)) (recur (inc idx)) (+ offset idx)))))) ~200 ns
  • 30. (defn matching-index [offset ks prefix] (let [cnt-ks (- (.count ^Counted ks) offset) cnt-prefix (Array/getLength prefix) cnt (Math/min cnt-ks cnt-prefix)] (loop [idx 0] (if (== cnt idx) (+ offset idx) (if (= (nth ks (+ offset idx)) (aget prefix idx)) (recur (inc idx)) (+ offset idx)))))) ~100 ns
  • 32. WHY IS IT SLOWER THAN JAVA? THE ETERNAL QUESTION:
  • 33. (+ 2 1) ! (+ (Long. 2) 1) ! (+ (/ 3 2) (/ 3 2)) ! (+ 2 (BigInteger. 1))
  • 35. > (use 'no.disassemble) nil ! > (defn log [x] (Math/log x)) #’log ! > (println (disassemble log))
  • 36. public final class user$log extends clojure.lang.AFunction { public static {}; ... public user$log(); ... public java.lang.Object invoke(java.lang.Object x); ... }
  • 37. public java.lang.Object invoke(java.lang.Object x); 0 aload_1 [x] 1 aconst_null 2 astore_1 [x] 3 checkcast java.lang.Number 6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double 9 invokestatic java.lang.Math.log(double) : double 12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double 15 areturn (fn [x] (Math/log x))
  • 38. public java.lang.Object invoke(java.lang.Object x); 0 aload_1 [x] 1 aconst_null 2 astore_1 [x] 3 checkcast java.lang.Number 6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double 9 invokestatic java.lang.Math.log(double) : double 12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double 15 areturn (fn [x] (Math/log x))
  • 39. public java.lang.Object invoke(java.lang.Object x); 0 aload_1 [x] 1 aconst_null 2 astore_1 [x] 3 checkcast java.lang.Number 6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double 9 invokestatic java.lang.Math.log(double) : double 12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double 15 areturn (fn [x] (Math/log x))
  • 40. public java.lang.Object invoke(java.lang.Object x); 0 aload_1 [x] 1 aconst_null 2 astore_1 [x] 3 checkcast java.lang.Number 6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double 9 invokestatic java.lang.Math.log(double) : double 12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double 15 areturn (fn [x] (Math/log x))
  • 41. public java.lang.Object invoke(java.lang.Object x); 0 aload_1 [x] 1 aconst_null 2 astore_1 [x] 3 checkcast java.lang.Number 6 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double 9 invokestatic java.lang.Math.log(double) : double 12 invokestatic java.lang.Double.valueOf(double) : java.lang.Double 15 areturn (fn [x] (Math/log x))
  • 42. (fn ^double [^double x] (Math/log x)) public java.lang.Object invoke(java.lang.Object arg0); 0 aload_0 1 aload_1 2 checkcast java.lang.Number 5 invokestatic clojure.lang.RT.doubleCast(java.lang.Object) : double 8 invokeinterface clojure.lang.IFn$DD.invokePrim(double) : double 13 new java.lang.Double 16 dup_x2 17 dup_x2 18 pop 19 invokespecial java.lang.Double(double) 22 areturn
  • 43. (fn ^double [^double x] (Math/log x)) public final double invokePrim(double x); 0 dload_1 [x] 1 invokestatic java.lang.Math.log(double) : double 4 dreturn
  • 44. (fn [x y] (Math/min x y)) public java.lang.Object invoke(java.lang.Object x, java.lang.Object y); 0 ldc <String "java.lang.Math"> 2 invokestatic java.lang.Class.forName(java.lang.String) : java.lang.Class 5 ldc <String "min"> 7 iconst_2 8 anewarray java.lang.Object 11 dup 12 iconst_0 13 aload_1 [x] 14 aconst_null 15 astore_1 [x] 16 aastore 17 dup 18 iconst_1 19 aload_2 [y] 20 aconst_null 21 astore_2 22 aastore 23 invokestatic clojure.lang.Reflector.invokeStaticMethod … 26 areturn
  • 45. (fn [x y] (+ x y)) public java.lang.Object invoke(java.lang.Object x, java.lang.Object y); 0 aload_1 [x] 1 aconst_null 2 astore_1 [x] 3 aload_2 [y] 4 aconst_null 5 astore_2 [y] 6 invokestatic clojure.lang.Numbers.add(java.lang.Object, java.lang.Object) … 9 areturn
  • 46. static public Number add(Object x, Object y){ return ops(x).combine(ops(y)).add((Number)x, (Number)y); }   class LongOps { final public Number add(Number x, Number y){ return num(Numbers.add(x.longValue(),y.longValue())); } }   static public long add(long x, long y){ long ret = x + y; if ((ret ^ x) < 0 && (ret ^ y) < 0) return throwIntOverflow(); return ret; } (fn [x y] (+ x y))
  • 47. (fn [^long x ^long y] (+ x y)) public final java.lang.Object invokePrim(long x, long arg1); 0 lload_1 [x] 1 lload_3 2 invokestatic clojure.lang.Numbers.add(long, long) : long 5 invokestatic clojure.lang.Numbers.num(long) : java.lang.Number 8 areturn
  • 48. (fn ^long [^long x ^long x] (+ x y)) public final long invokePrim(long x, long arg1); 0 lload_1 [x] 1 lload_3 2 invokestatic clojure.lang.Numbers.add(long, long) : long 5 lreturn  
  • 49. (fn ^long [^long x ^long y] (unchecked-add x y)) public final long invokePrim(long x, long arg1); 0 lload_1 [x] 1 lload_3 2 ladd 5 lreturn  
  • 50. (fn ^long [^long x ^long y] (unchecked-add x y)) AS FAST AS JAVA! public final long invokePrim(long x, long arg1); 0 lload_1 [x] 1 lload_3 2 ladd 5 lreturn  
  • 51. (fn [x y] (unchecked-add x y)) public java.lang.Object invoke(java.lang.Object x, java.lang.Object y); 0 aload_1 [x] 1 aconst_null 2 astore_1 [x] 3 aload_2 [y] 4 aconst_null 5 astore_2 [y] 6 invokestatic clojure.lang.Numbers.unchecked_add(java.lang.Object, … 9 areturn
  • 53. public class Primitives { ! … ! public static long add(long a, long b) { return a + b; }   public static double add(double a, double b) { return a + b; } ! … ! }
  • 54. > (require '[primitive-math :as p]) nil ! > (macroexpand '(p/+ x y)) (. primitive_math.Primitives add x y)
  • 55. (fn ^long [^long x ^long y] (p/+ x y)) public final long invokePrim(long x, long arg1); 0 lload_1 [x] 1 lload_3 2 invokestatic primitive_math.Primitives.add(long, long) : long 5 lreturn
  • 56. > (set! *warn-on-reflection* true) true ! > (fn [x y] (unchecked-add x y)) #<...> ! > (fn [x y] (p/+ x y)) Reflection warning - call to add can't be resolved. #<...>
  • 57. • does not supplant Clojure’s numerics • invariants via feedback when they aren’t satisfied • using Java isn’t cheating
  • 60. (quick-bench (.getBytes "a reasonably long string")) (let [f (memoize identity)] (quick-bench (f 1))) ~60 ns ~100 ns
  • 61. (defn memoize [f] (let [mem (atom {})] (fn [& args] (if-let [e (find @mem args)] (val e) (let [ret (apply f args)] (swap! mem assoc args ret) ret)))))
  • 62. {} or (array-map) (hash-map) • up to eight calls to .equiv() A LOOKUP • one call to .hasheq(), approx. one call to .equiv()
  • 63. if(obj instanceof IPersistentVector) { Collection ma = (Collection) obj; if (ma.size() != v.count()) return false; for(Iterator i1 = ((List) v).iterator(), i2 = ma.iterator(); i1.hasNext();) { if (!Util.equiv(i1.next(), i2.next())) return false; } return true; }
  • 65. (deftype Tuple0 []) ! (deftype Tuple1 [a]) ! (deftype Tuple2 [a b]) ! (deftype Tuple3 [a b c]) ! …
  • 66. (if (instance? ~name x##) ~(if (zero? cardinality) true `(and ~@(map (fn [f] `(Util/equiv ~f (. ~other ~f))) fields))) …)
  • 67. (let [v [1 2 3]] (quick-bench (nth v 0))) (let [v [1 2 3]] (quick-bench (first v))) ~5 ns ~50 ns
  • 68. (let [t (tuple 1 2 3)] (quick-bench (nth t 0))) (let [t (tuple 1 2 3)] (quick-bench (first t))) ~5 ns ~5 ns
  • 69. • if you can, do the hard work once • if you don’t control the context, assume every bit matters
  • 70. • if you can, do the hard work at compile-time • the tools for library-sized macros are a bit lacking right now
  • 71. I WORK WITH THIS GUY (he is programming)
  • 74. (let-mutable [x 0] (dotimes [_ 100] (set! x (inc x))) x)
  • 75. (let [x (LongContainer. 0)] (dotimes [_ 100] (.set x (inc (.get x)))) (.get x))
  • 76. (let-mutable [x 1] (fn [] x)) (let [x (LongContainer. 1)] (let [x (.get x)] (fn [] x)))
  • 77. • Clojure’s general solutions are fairly pessimistic, and assume few invariants • try creating a more optimistic context
  • 78. YOU DON’T HAVETO DO WHAT HE DID
  • 80. SOME FINALTHOUGHTS • be curious about the tools you use • if you’re going for a bounded solution, describe the boundaries fully • if you’re going for a general solution, make sure it’s actually general
  • 81.