Clojure High Performance Programming - Second Edition

Book description

Become an expert at writing fast and high performant code in Clojure 1.7.0

About This Book

  • Enhance code performance by using appropriate Clojure features
  • Improve the efficiency of applications and plan their deployment
  • A hands-on guide to designing Clojure programs to get the best performance

Who This Book Is For

This book is intended for intermediate Clojure developers who are looking to get a good grip on achieving optimum performance. Having a basic knowledge of Java would be helpful.

What You Will Learn

  • Identify performance issues in Clojure programs using different profiling tools
  • Master techniques to achieve numerical performance in Clojure
  • Use Criterium library to measure latency of Clojure expressions
  • Exploit Java features in Clojure code to enhance performance
  • Avoid reflection and boxing with type hints
  • Understand Clojure's concurrency and state-management primitives in depth
  • Measure and monitor performance, and understand optimization techniques

In Detail

Clojure treats code as data and has a macro system. It focuses on programming with immutable values and explicit progression-of-time constructs, which are intended to facilitate the development of more robust programs, particularly multithreaded ones. It is built with performance, pragmatism, and simplicity in mind. Like most general purpose languages, various Clojure features have different performance characteristics that one should know in order to write high performance code.

This book shows you how to evaluate the performance implications of various Clojure abstractions, discover their underpinnings, and apply the right approach for optimum performance in real-world programs.

It starts by helping you classify various use cases and the need for them with respect to performance and analysis of various performance aspects. You will also learn the performance vocabulary that experts use throughout the world and discover various Clojure data structures, abstractions, and their performance characteristics. Further, the book will guide you through enhancing performance by using Java interoperability and JVM-specific features from Clojure. It also highlights the importance of using the right concurrent data structure and Java concurrency abstractions.

This book also sheds light on performance metrics for measuring, how to measure, and how to visualize and monitor the collected data. At the end of the book, you will learn to run a performance profiler, identify bottlenecks, tune performance, and refactor code to get a better performance.

Style and approach

An easy-to-follow guide full of real-world examples and self-sufficient code snippets that will help you get your hands dirty with high performance programming with Clojure.

Table of contents

  1. Clojure High Performance Programming Second Edition
    1. Table of Contents
    2. Clojure High Performance Programming Second Edition
    3. Credits
    4. About the Author
    5. About the Reviewers
      1. Support files, eBooks, discount offers, and more
        1. Why subscribe?
        2. Free access for Packt account holders
    7. Preface
      1. What this book covers
      2. What you need for this book
      3. Who this book is for
      4. Conventions
      5. Reader feedback
      6. Customer support
        1. Errata
        2. Piracy
        3. eBooks, discount offers, and more
        4. Questions
    8. 1. Performance by Design
      1. Use case classification
        1. The user-facing software
        2. Computational and data-processing tasks
          1. A CPU bound computation
          2. A memory bound task
          3. A cache bound task
          4. An input/output bound task
        3. Online transaction processing
        4. Online analytical processing
        5. Batch processing
      2. A structured approach to the performance
      3. The performance vocabulary
        1. Latency
        2. Throughput
        3. Bandwidth
        4. Baseline and benchmark
        5. Profiling
        6. Performance optimization
        7. Concurrency and parallelism
        8. Resource utilization
        9. Workload
      4. The latency numbers that every programmer should know
      5. Summary
    9. 2. Clojure Abstractions
      1. Non-numeric scalars and interning
      2. Identity, value, and epochal time model
        1. Variables and mutation
        2. Collection types
      3. Persistent data structures
        1. Constructing lesser-used data structures
        2. Complexity guarantee
          1. O(<7) implies near constant time
        3. The concatenation of persistent data structures
      4. Sequences and laziness
        1. Laziness
          1. Laziness in data structure operations
          2. Constructing lazy sequences
            1. Custom chunking
            2. Macros and closures
      5. Transducers
        1. Performance characteristics
      6. Transients
        1. Fast repetition
      7. Performance miscellanea
        1. Disabling assertions in production
        2. Destructuring
        3. Recursion and tail-call optimization (TCO)
          1. Premature end of iteration
        4. Multimethods versus protocols
        5. Inlining
      8. Summary
    10. 3. Leaning on Java
      1. Inspecting the equivalent Java source for Clojure code
        1. Creating a new project
        2. Compiling the Clojure sources into Java bytecode
        3. Decompiling the .class files into Java source
        4. Compiling the Clojure source without locals clearing
      2. Numerics, boxing, and primitives
      3. Arrays
      4. Reflection and type hints
        1. An array of primitives
        2. Primitives
        3. Macros and metadata
          1. String concatenation
        4. Miscellaneous
      5. Using array/numeric libraries for efficiency
        1. HipHip
        2. primitive-math
          1. Detecting boxed math
      6. Resorting to Java and native code
        1. Proteus – mutable locals in Clojure
      7. Summary
    11. 4. Host Performance
      1. The hardware
        1. Processors
          1. Branch prediction
          2. Instruction scheduling
          3. Threads and cores
        2. Memory systems
          1. Cache
          2. Interconnect
        3. Storage and networking
      2. The Java Virtual Machine
        1. The just-in-time compiler
        2. Memory organization
        3. HotSpot heap and garbage collection
        4. Measuring memory (heap/stack) usage
          1. Determining program workload type
        5. Tackling memory inefficiency
      3. Measuring latency with Criterium
        1. Criterium and Leiningen
      4. Summary
    12. 5. Concurrency
      1. Low-level concurrency
        1. Hardware memory barrier (fence) instructions
        2. Java support and the Clojure equivalent
      2. Atomic updates and state
        1. Atomic updates in Java
        2. Clojure's support for atomic updates
          1. Faster writes with atom striping
      3. Asynchronous agents and state
        1. Asynchrony, queueing, and error handling
        2. Why you should use agents
        3. Nesting
      4. Coordinated transactional ref and state
        1. Ref characteristics
        2. Ref history and in-transaction deref operations
        3. Transaction retries and barging
        4. Upping transaction consistency with ensure
        5. Lesser transaction retries with commutative operations
        6. Agents can participate in transactions
        7. Nested transactions
        8. Performance considerations
      5. Dynamic var binding and state
      6. Validating and watching the reference types
      7. Java concurrent data structures
        1. Concurrent maps
        2. Concurrent queues
        3. Clojure support for concurrent queues
      8. Concurrency with threads
        1. JVM support for threads
        2. Thread pools in the JVM
        3. Clojure concurrency support
          1. Future
          2. Promise
      9. Clojure parallelization and the JVM
        1. Moore's law
        2. Amdahl's law
        3. Universal Scalability Law
        4. Clojure support for parallelization
          1. pmap
          2. pcalls
          3. pvalues
        5. Java 7's fork/join framework
      10. Parallelism with reducers
        1. Reducible, reducer function, reduction transformation
        2. Realizing reducible collections
        3. Foldable collections and parallelism
      11. Summary
    13. 6. Measuring Performance
      1. Performance measurement and statistics
        1. A tiny statistics terminology primer
          1. Median, first quartile, third quartile
          2. Percentile
          3. Variance and standard deviation
        2. Understanding Criterium output
        3. Guided performance objectives
      2. Performance testing
        1. The test environment
        2. What to test
        3. Measuring latency
          1. Comparative latency measurement
          2. Latency measurement under concurrency
        4. Measuring throughput
          1. Average throughput test
        5. The load, stress, and endurance tests
      3. Performance monitoring
        1. Monitoring through logs
        2. Ring (web) monitoring
        3. Introspection
          1. JVM instrumentation via JMX
      4. Profiling
        1. OS and CPU/cache-level profiling
        2. I/O profiling
      5. Summary
    14. 7. Performance Optimization
      1. Project setup
        1. Software versions
        2. Leiningen project.clj configuration
          1. Enable reflection warning
          2. Enable optimized JVM options when benchmarking
        3. Distinguish between initialization and runtime
      2. Identifying performance bottlenecks
        1. Latency bottlenecks in Clojure code
          1. Measure only when it is hot
        2. Garbage collection bottlenecks
          1. Threads waiting at GC safepoint
          2. Using jstat to probe GC details
        3. Inspecting generated bytecode for Clojure source
        4. Throughput bottlenecks
      3. Profiling code with VisualVM
      4. The Monitor tab
        1. The Threads tab
        2. The Sampler tab
          1. Setting the thread name
        3. The Profiler tab
        4. The Visual GC tab
        5. The Alternate profilers
      5. Performance tuning
        1. Tuning Clojure code
          1. CPU/cache bound
          2. Memory bound
          3. Multi-threaded
        2. I/O bound
        3. JVM tuning
        4. Back pressure
      6. Summary
    15. 8. Application Performance
      1. Choosing libraries
        1. Making a choice via benchmarks
          1. Web servers
          2. Web routing libraries
          3. Data serialization
          4. JSON serialization
          5. JDBC
      2. Logging
        1. Why SLF4J/LogBack?
        2. The setup
          1. Dependencies
          2. The logback configuration file
          3. Optimization
      3. Data sizing
        1. Reduced serialization
        2. Chunking to reduce memory pressure
          1. Sizing for file/network operations
          2. Sizing for JDBC query results
      4. Resource pooling
        1. JDBC resource pooling
      5. I/O batching and throttling
        1. JDBC batch operations
        2. Batch support at API level
        3. Throttling requests to services
      6. Precomputing and caching
      7. Concurrent pipelines
        1. Distributed pipelines
      8. Applying back pressure
        1. Thread pool queues
        2. Servlet containers such as Tomcat and Jetty
        3. HTTP Kit
        4. Aleph
      9. Performance and queueing theory
        1. Little's law
          1. Performance tuning with respect to Little's law
      10. Summary
    16. Index

Product information

  • Title: Clojure High Performance Programming - Second Edition
  • Author(s): Shantanu Kumar
  • Release date: September 2015
  • Publisher(s): Packt Publishing
  • ISBN: 9781785283642