Interview
Performance & Tuning — Interview Questions (60+)
Detailed Questions
1. How do you approach performance problems?
- Short: Measure first, find the bottleneck, fix, re-measure.
- Detailed: Avoid premature optimization. Establish a baseline and a target, profile (CPU, allocation, GC, locks), fix the dominant bottleneck, and verify with benchmarks. Optimize algorithms before micro-tuning.
- Example: Profiling reveals an O(n²) loop—fix the algorithm, not the syntax.
2. How do you benchmark Java correctly?
- Short: Use JMH; account for JIT warmup.
- Detailed: Naive
System.nanoTime()loops are misleading due to JIT warmup, dead-code elimination, and GC. JMH handles warmup iterations, forks, and blackholes to prevent the optimizer from removing your code. - Example:
@Benchmarkmethods withBlackhole.
3. Common Java performance pitfalls?
- Short: Autoboxing, string concat in loops, wrong data structures, excessive allocation.
- Detailed: Boxing in tight loops,
+concatenation in loops (use StringBuilder),LinkedListwhereArrayListfits, unbounded caches, logging in hot paths, and synchronized when atomics suffice. - Example: Replace
Integeraccumulation withint/IntStream.
4. How does GC affect performance and how to tune it?
- Short: Pauses + allocation rate; tune GC choice and heap.
- Detailed: High allocation → frequent GC. Reduce allocations, reuse buffers, right-size the heap, and pick a GC matching the goal (Parallel for throughput, G1 default, ZGC/Shenandoah for latency). Measure with GC logs before tuning.
- Example: Latency-sensitive service → ZGC + adequate heap.
5. How to find and fix a memory leak?
- Short: Heap dump → analyze retained sets → remove lingering refs.
- Detailed: Capture with
-XX:+HeapDumpOnOutOfMemoryError/jcmd, analyze with MAT/VisualVM, look for growing static collections, caches, ThreadLocals, and listeners. Fix by bounding caches, weak refs, and proper cleanup. - Example: A static
Mapused as a cache without eviction.
6. CPU-bound vs I/O-bound tuning?
- Short: CPU: ~#cores threads, better algorithms; I/O: more concurrency/async.
- Detailed: CPU-bound work saturates cores—reduce work, parallelize with ForkJoin, size pools near core count. I/O-bound work waits—use async/non-blocking or virtual threads and higher concurrency.
- Example: Many DB calls → virtual threads; matrix math → ForkJoin.
Rapid-Fire (Q → A)
- First rule of optimization? → Measure.
- Premature optimization? → Root of much evil.
- Profiler examples? → JFR, async-profiler, VisualVM.
- Benchmark tool? → JMH.
- Why not nanoTime loops? → JIT/GC distortion.
- Warmup matters because? → JIT compiles hot code.
- Dead-code elimination? → Optimizer removes unused results.
- Blackhole? → Prevents DCE in JMH.
- Big-O first? → Algorithmic complexity dominates.
- String concat in loop? → Use StringBuilder.
- Autoboxing cost? → Allocation/unbox.
- Primitive streams? → Avoid boxing.
- ArrayList vs LinkedList perf? → ArrayList usually faster.
- HashMap sizing? → Pre-size to avoid rehash.
- Object allocation cost? → Pressure on GC.
- Object pooling? → Only for expensive objects.
- Escape analysis? → May stack-allocate.
- Lock contention symptom? → Threads blocked.
- Reduce contention? → Finer locks/atomics/striping.
- LongAdder vs AtomicLong? → Better under contention.
- False sharing fix? → Padding/@Contended.
- volatile cost? → Cheap read, ordered write.
- synchronized cost? → Uncontended cheap, contended expensive.
- ThreadLocal perf use? → Avoid shared contention.
- GC log flag? → -Xlog:gc*.
- High allocation rate? → More GC pauses.
- Reduce allocations? → Reuse, primitives, streams care.
- Heap too small? → Frequent GC/OOM.
- Heap too large? → Long pauses (older GCs).
- Set Xms=Xmx? → Avoid resize pauses.
- Choose Parallel GC? → Throughput batch.
- Choose G1? → Balanced default.
- Choose ZGC? → Low latency/large heap.
- Compressed oops? → Heap < 32GB.
- Off-heap memory? → Direct ByteBuffers.
- Memory-mapped files? → Fast large file I/O.
- Buffered I/O? → Reduce syscalls.
- NIO benefit? → Non-blocking/selectors.
- Connection pooling? → Reuse DB connections.
- N+1 query problem? → Batch/join instead.
- Index missing symptom? → Full table scans.
- Caching benefit? → Avoid repeated work.
- Cache hit ratio? → Effectiveness metric.
- Lazy loading? → Defer expensive work.
- Batch processing? → Amortize overhead.
- Vectorization? → SIMD via JIT.
- Inlining? → Removes call overhead.
- Loop unrolling? → Fewer branches.
- Branch misprediction? → Pipeline stalls.
- Cache locality? → Sequential access faster.
- Array vs linked traversal? → Array better locality.
- StringBuilder capacity? → Preset to avoid growth.
- Regex precompile? → Reuse Pattern.
- Logging in hot path? → Guard/parameterize.
- Reflection cost? → Cache MethodHandles.
- Serialization cost? → Prefer efficient formats.
- JSON parsing cost? → Stream/large payloads.
- Thread pool sizing CPU-bound? → ~#cores.
- Thread pool sizing I/O-bound? → Higher/virtual threads.
- Little's Law? → L = λ × W (concurrency = arrival × latency).
- Throughput vs latency trade-off? → Batch increases both differently.
- Tail latency (p99)? → Worst-case user experience.
- Reduce p99? → Timeouts, hedging, isolation.
- Golden rule? → Profile, fix the biggest bottleneck, verify, repeat.