to develop and evaluate things on the fly • ease maintenance production • scalability (doh) • integration with well-known / existing tools • good, stable runtime • runtime debugging toolkit • performance What are you looking for? Friday, October 26, 12
`lein repl` in your console • emacs (it’s written in lisp, you know?) excellent nrepl and (older thing) clojure-swank, paredit-mode, formatting • nrepl get to the guts of runtime • VisualVm and the rest of Java goodness like jmap, jstack, jstat etc etc etc Sane development environment Friday, October 26, 12
• No shared mutable state • No locks • Pure functions -> same input -> same output • Easy composition and pipelining Easy maintenance in production Friday, October 26, 12
can eat out all the memory, right? • Painless parallel execution • Memory efficiency as far as it is possible with lisps, of course. in my mind that was mostly about structural sharing & persistent DS • JIT / inlining Scalability You keep using that word. I do not think it means what you think it means. (voice in my head) Friday, October 26, 12
libraries are either ported to Clojure, or use Java library underneath • Your favorite Java application container / web server • Jar packaging / public / private Maven repositories • Not to replace, but to complement your existing JVM toolkit Integration Friday, October 26, 12
efficient creation of “modified” versions • structural sharing • inherently thread & iteration-safe will not mutate in a middle • immutable modification yields new coll • composite Persistent DSs? Friday, October 26, 12
/ vars • transactional memory access yes, with retries • no user locks, no deadlocks • mutation through pure function • coordinated • readers can read value at any point in time STM?.. Friday, October 26, 12
app "_" env))) ;; (get-locator “my-cool-app” “production”) ;; => :my-cool-app_production (defn get-or-create-store ([locator] (if-let [store (get @events locator)] ;; If the store does exists return reference to it store (do ;; If the store does not exist yet, create it (swap! events assoc locator (ref [])) (get @events locator)))) ([app env] (get-or-create-store (get-locator app env))) Friday, October 26, 12
it :md5 "cd0e351d2eefdf0f79e0b55a0efe543b", ;; Arbitrary additional info :additional_info {:execution_time 0.5469999, :url “http://mysite.com/page0” }, ;; Event Type identifier (404, exception, page load time) :type "page_load", ;; Dispatcher host name :hostname "dc0-web01", ;; Time when event was received :received_at ..., ;; Tags assigned to the event :tags ["metrics" "performance"] } Friday, October 26, 12
;; Start a transaction (dosync ;; It doesn’t really matter in which order we receive ;; events, as we receive them very often. So let’s use ;; commute. (conj) is commutative, so we will get (almost) ;; same result no matter what was the order of the received ;; events (commute store conj m)))) Friday, October 26, 12
types-grouped (group-by #(:type %) collection)] (apply-to-values types-grouped (fn [app-with-type] {:count (count all-with-type)})))) @events)) v group all the events by type Friday, October 26, 12
types-grouped (group-by #(:type %) collection)] (apply-to-values types-grouped (fn [app-with-type] {:count (count all-with-type)})))) @events)) apply fn to all values of a hash Friday, October 26, 12
`(let [store# (deref (get-or-create-store ~app ~env))] (binding [*collection* (filter ~flt store#)] ~@body))) macro that will filter the collection for us, and put results for execution in binding Friday, October 26, 12
`(let [store# (deref (get-or-create-store ~app ~env))] (binding [*collection* (filter ~flt store#)] ~@body))) body will be evaluated in scope of binding so we could operate the filtered collection without referencing it elsewhere Friday, October 26, 12
`(let [store# (deref (get-or-create-store ~app ~env))] (binding [*collection* (filter ~flt store#)] ~@body))) filter function is applied to all entries, and only those that match will make it to *collection* Friday, October 26, 12
(fn [i] (get-in i [:additional_info :execution_time])) *collection*)] (/ (apply + page-load-times) (count page-load-times)))) filter by page_load type get only execution times sum! count average Friday, October 26, 12
processing (big) data • Big set of available tools • Tools are easy-to-use, next-level • Will change the way you write programs • Benefits ahead Takeaway Friday, October 26, 12