Java testing notes

Test objects Dummy – returns default value

  • Stub – returns a valid predefined value
  • Mock – contains some logic
  • Fakes – valid but generated data

Testing persistence -> stubing/mocking entity manager or faking a data from in-memory database

BDD -> cucumber

Useful tools: EqualsVerifier, Testing RxJava, Hamcrest matchers

Spock – high level groovy based framework, can work over junit and cucumber, nice and concise syntax

Static code analysis of test coverage – cobertura

WEB testing – selenium, arquillian

htmlunit – simple html client for testing WEB app

pageunit – checking up-ness

Static code analysis – xlint javac’s option, PMD (command line, eclipse addon, maven plugin), checkstyle, CPD

Bytecode analysis – FindBugs, Fortify

Java performance extract

Benchmarks:

  • micro
  • meso
  • macro

Tools

  • non Java: CPU, disk, network
  • Java tools: flags, heap, GC

Profilers: sampling, instrumentation, native

JIT: client (default threshold is 1500), server (default threshold is 10000), tiered compilation

Tuning JIT:

  • code cache
  • compilation thresholds – how many times code will be interpreted before gets compiled
  • print compilation process logs
  • compilation thread (amount can be adjusted)
  • inlining (limits of code for inline – default 325 bytes)
  • escape analysis mode, very efficient, but will break improperly synchronized code
  • de-optimisation
  • tiered compilation levels

GC: serial, throughput (parallel), concurrent (CMS), G1

GC generation: new (eden, survived), old

All GC do stop-the-world pause while checking the eden, for not eden, CMS and G1 may do (lower CPU consumption) or with not stop-the-world pause (high CPU consumption)

Serial GC (x32, single core machine or Windows) – for client:

  • single threaded
  • stop-the-world for new or old generation processing

Throughput (Unix, multi-core, x62):

  • multi-threaded
  • stop-the-world for new or old generation processing

CMS:

– multiple threads for new generation

  • for old generation, one thread scans object to free in background with no stop, but old generation remains fragmented, stop-the-world still happens, but quite rare, to defragment the old generation heap, usually it happens when there is no space to allocate for new object

G1:

  • for large heaps (more than 4GB), marker heap with a region
  • System.gc() does stop-the-wrold for all types of GC and do full scan

Tuning GC:

  • sizing heap (small – too often GC works, big – OS swapping of RAM and drive)
  • sizing generations
  • Permgen/MetaSpace – keeps information about loaded classes – is expensive operation for resizing, it is better to define at startup
  • Controlling amount of GC threads
  • adaptive sizing (should be turned-on)
  • large object

Tuning threads:

  • pool size
  • thread stack size
  • avoid synchronization
  • thread priorities
  • adjusting spinning

Persistence

  • choose right driver (try different)
  • prepared statement and statement pooling
  • connection pools
  • transaction pools
  • cached queries

Other optimisations:

  • reuse Random
  • JNI is not solution for performance
  • Exceptions are not always an issue
  • One line string concatenation is faster then multiline
  • Lambdas and anonymous classes has the same performance, but lambdas loaded faster