Working with Performance Optimization

1. Profiling Java Applications

ToolUse
JFR (Java Flight Recorder)Built-in, low overhead
JMC (Mission Control)Analyze JFR recordings
async-profilerSampling, flame graphs
YourKit, JProfilerCommercial profilers

2. Using JMH for Benchmarking

Example: JMH benchmark

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
public class StringConcatBench {
    @Benchmark
    public String plus()    { return "a" + 1 + "b"; }
    @Benchmark
    public String builder() { return new StringBuilder("a").append(1).append("b").toString(); }
}
AnnotationUse
@BenchmarkMark method
@StatePer-thread/benchmark state
@Setup / @TearDownLifecycle
BlackholePrevent dead-code elimination

3. Optimizing String Operations

PracticeDetail
Concat in loopsUse StringBuilder
Java 9+ +Compiles to invokedynamic — usually fast
String.intern()Save memory for repeated strings (caution)
Compact stringsJava 9+ uses byte[] for Latin-1 strings

4. Optimizing Collection Performance

TipDetail
Pre-sizenew ArrayList<>(expectedSize)
Right typeArrayList for index access; LinkedList for queue
EnumMap/EnumSetFar more efficient than HashMap for enums
Avoid boxingUse IntStream / primitive arrays for hot paths

5. Reducing Object Creation

PracticeDetail
Reuse immutablesCache constants
Avoid auto-boxingUse primitive specializations
Builder reuseReset and reuse where safe
Escape analysisJIT may stack-allocate small short-lived objects

6. Using Object Pooling Wisely

WhenDetail
Good forExpensive resources (connections, threads)
Avoid forSmall/short-lived objects (GC is faster)

7. Optimizing I/O Operations

PracticeDetail
Buffered streamsBufferedReader/Writer/InputStream/OutputStream
NIO channelsFor high throughput
Memory-mapped filesFileChannel.map() for large files
Async I/OJava 21+: virtual threads make sync APIs scale

8. Tuning JVM Parameters

ParamEffect
-Xmx / -XmsHeap; set equal to avoid resizing
-XX:+UseG1GC / +UseZGCGC choice
-XX:MaxGCPauseMillisPause target
-XX:+UseStringDeduplicationSave memory in G1

9. Understanding Escape Analysis

OptimizationDetail
Scalar replacementDecompose unescaped objects into fields
Stack allocationConceptual; usually scalar replaced
Lock elisionSkip sync on thread-local objects

10. Using Inline Caches

AspectDetail
Monomorphic1 receiver type — inlined fast path
Bimorphic2 types — inlined with check
MegamorphicMany types — vtable dispatch
PracticeAvoid swarms of types behind virtual calls

11. Optimizing Lambda Performance

AspectDetail
Stateless lambdasCached as singletons
Capturing lambdasAllocate per call — avoid in hot loops
JITInlines monomorphic call sites

12. Reducing GC Pressure

StrategyDetail
Reuse buffersByteBuffer/StringBuilder
Pre-size collectionsAvoid resize churn
Avoid boxingPrimitive arrays/streams
Off-heapDirect ByteBuffer for large data
Profile allocationsJFR allocation profiling

13. Understanding Branch Prediction

PracticeDetail
Predictable branchesSort data to make branches consistent
BranchlessUse bit manipulation when feasible
Hot path firstCommon case as straight-line code