Facebook Pixel
Searching...
English
EnglishEnglish
EspañolSpanish
简体中文Chinese
FrançaisFrench
DeutschGerman
日本語Japanese
PortuguêsPortuguese
ItalianoItalian
한국어Korean
РусскийRussian
NederlandsDutch
العربيةArabic
PolskiPolish
हिन्दीHindi
Tiếng ViệtVietnamese
SvenskaSwedish
ΕλληνικάGreek
TürkçeTurkish
ไทยThai
ČeštinaCzech
RomânăRomanian
MagyarHungarian
УкраїнськаUkrainian
Bahasa IndonesiaIndonesian
DanskDanish
SuomiFinnish
БългарскиBulgarian
עבריתHebrew
NorskNorwegian
HrvatskiCroatian
CatalàCatalan
SlovenčinaSlovak
LietuviųLithuanian
SlovenščinaSlovenian
СрпскиSerbian
EestiEstonian
LatviešuLatvian
فارسیPersian
മലയാളംMalayalam
தமிழ்Tamil
اردوUrdu
Java Performance

Java Performance

The Definitive Guide: Getting the Most Out of Your Code
by Scott Oaks 2014 426 pages
4.38
100+ ratings
Listen

Key Takeaways

1. Optimize Java performance through strategic tuning and best practices

There is no magical -XX:+RunReallyFast option.

Performance is multifaceted. Java performance optimization involves a combination of writing efficient algorithms, tuning the JVM, and implementing best coding practices. It's not just about tweaking JVM flags, but also about understanding how Java works under the hood.

Measure, don't guess. Always profile your application before making optimizations. Use tools like jconsole, jstat, and Java Flight Recorder to gather data about your application's performance. Look for bottlenecks in CPU usage, memory allocation, and garbage collection.

Balance trade-offs. Performance optimization often involves trade-offs. For example:

  • Increasing heap size can reduce GC frequency but may increase pause times
  • Using more threads can improve throughput but may lead to increased context switching
  • Aggressive inlining can speed up method calls but increase code size

Always test your optimizations in a realistic environment to ensure they provide the expected benefits without introducing new problems.

2. Master garbage collection for efficient memory management

GC engineers around the world are now groaning, since either of these techniques hampers the efficiency of GC.

Understand GC algorithms. Java offers several garbage collection algorithms, each with its strengths:

  • Serial GC: Simple and efficient for small heaps and single-threaded applications
  • Parallel GC: Focuses on maximizing throughput, good for batch processing
  • CMS (Concurrent Mark Sweep): Aims to minimize pause times, suitable for responsive applications
  • G1 (Garbage First): Balances throughput and pause times, good for large heaps

Tune GC parameters. Adjust GC parameters based on your application's needs:

  • Set appropriate heap sizes (-Xms and -Xmx)
  • Adjust generation sizes (e.g., -XX:NewRatio)
  • Configure GC logging for analysis (-XX:+UseGCLogFileRotation)

Minimize object churn. Reduce the rate of object creation and garbage:

  • Use object pools for expensive-to-create objects
  • Prefer primitive types over wrapper classes when possible
  • Use StringBuilder for string concatenation in loops

Remember, the goal is not to eliminate GC but to make it efficient and predictable.

3. Leverage thread pools and synchronization for optimal concurrency

Thread pools are one case where object pooling is a good thing: threads are expensive to initialize, and a thread pool allows the number of threads on a system to be easily throttled.

Use thread pools wisely. Thread pools help manage concurrency efficiently:

  • Choose an appropriate pool size based on available CPUs and workload characteristics
  • Use different pool types for different scenarios (e.g., FixedThreadPool, CachedThreadPool)
  • Consider using a ForkJoinPool for divide-and-conquer algorithms

Minimize synchronization. Excessive synchronization can hurt performance:

  • Use concurrent collections when possible (e.g., ConcurrentHashMap)
  • Prefer atomic variables over synchronized blocks for simple operations
  • Use the synchronized keyword judiciously, synchronizing on the smallest possible code block

Avoid contention. High contention for shared resources can lead to poor scalability:

  • Use thread-local variables to eliminate sharing where possible
  • Consider using lock-free algorithms for highly contended operations
  • Be aware of false sharing and use appropriate padding techniques when necessary

4. Utilize profiling tools to identify and resolve performance bottlenecks

Profilers are the most important tool in a performance analyst's toolbox.

Choose the right profiler. Different profilers offer various insights:

  • Sampling profilers: Low overhead, good for production environments
  • Instrumented profilers: More detailed, but higher overhead
  • Native profilers: Can profile JVM internals and native code

Analyze profiler output. Look for:

  • Hot methods: Methods consuming the most CPU time
  • Allocation hot spots: Places where many objects are created
  • Lock contention: Methods spending time waiting for locks

Combine profiling techniques. Use multiple approaches for a comprehensive view:

  • CPU profiling to find computational bottlenecks
  • Memory profiling to identify memory leaks and excessive allocations
  • Thread profiling to detect deadlocks and synchronization issues

Remember that profilers can affect application behavior, so always verify findings in a non-profiled environment.

5. Implement effective memory management techniques

Eliminating duplicate copies of immutable objects via canonicalization can greatly decrease the amount of heap an application uses.

Minimize object creation. Excessive object creation can strain the garbage collector:

  • Use object pools for expensive-to-create objects
  • Employ the Flyweight pattern for shared, immutable objects
  • Utilize String.intern() for frequently used strings

Optimize collections. Choose appropriate collection types and sizes:

  • Use ArrayList instead of LinkedList for random access
  • Specify initial capacity for collections when size is known
  • Consider using primitive collections (e.g., TIntArrayList) to avoid boxing

Manage large objects carefully. Large objects can cause fragmentation and long GC pauses:

  • Use off-heap memory (e.g., ByteBuffer.allocateDirect()) for very large arrays
  • Consider breaking large objects into smaller chunks
  • Be cautious with finalizers, as they can delay object reclamation

6. Harness the power of JIT compilation for enhanced performance

There are a lot of details about Java that affect the performance of an application, and a lot of tuning flags are discussed. But there is no magical -XX:+RunReallyFast option.

Understand JIT basics. The Just-In-Time compiler optimizes frequently executed code:

  • Code starts in interpreted mode and is compiled as it becomes "hot"
  • Compiled code is stored in the code cache for future use
  • The JIT can perform aggressive optimizations based on runtime information

Choose the right compiler. Java offers different compiler modes:

  • Client: Fast startup, good for desktop applications
  • Server: Better long-term performance, suitable for long-running server applications
  • Tiered: Combines client and server modes for balanced performance

Fine-tune compilation. Adjust compilation behavior if needed:

  • Control inlining with -XX:MaxInlineSize and -XX:FreqInlineSize
  • Adjust the code cache size with -XX:ReservedCodeCacheSize
  • Use -XX:+PrintCompilation to understand compilation behavior

Remember that most applications perform well with default JIT settings, so only tune when necessary and after thorough profiling.

7. Optimize native memory usage and footprint

The total of native and heap memory used by the JVM yields the total footprint of an application.

Monitor native memory usage. Native memory can be a significant part of JVM footprint:

  • Use tools like jcmd with VM.native_memory to track native memory allocation
  • Monitor the resident set size (RSS) of the JVM process
  • Be aware of memory-mapped files and direct ByteBuffers

Optimize memory-mapped I/O. When using NIO:

  • Reuse direct ByteBuffers to avoid allocation overhead
  • Consider memory-mapped files for large datasets
  • Be cautious with off-heap allocations, as they're not subject to GC

Tune native memory settings. Adjust native memory parameters:

  • Set -XX:MaxDirectMemorySize to limit direct ByteBuffer allocations
  • Use -XX:NativeMemoryTracking=summary for detailed native memory usage
  • Consider using compressed ordinary object pointers (-XX:+UseCompressedOops) for 64-bit JVMs with heaps < 32GB

8. Leverage Java 8 features for improved performance and parallelism

Features in Java 8 that use automatic parallelization will use a common instance of the ForkJoinPool class.

Utilize streams for concise, parallel operations. Java 8 streams offer easy parallelization:

  • Use parallel streams for CPU-intensive operations on large datasets
  • Be cautious with I/O-bound or ordering-dependent operations in parallel streams
  • Adjust the common ForkJoinPool size with java.util.concurrent.ForkJoinPool.common.parallelism

Leverage new concurrent utilities. Java 8 introduces new tools for concurrency:

  • Use LongAdder instead of AtomicLong for high-contention counters
  • Employ StampedLock for read-write locks with optimistic reading
  • Utilize CompletableFuture for complex asynchronous operations

Optimize with lambda expressions and method references. These can lead to more efficient code:

  • Use method references instead of lambdas where possible for better inlining
  • Leverage the new functional interfaces in java.util.function package
  • Be aware that excessive use of tiny lambdas can increase pressure on the JIT compiler

Remember that while Java 8 features can improve performance, they're not a silver bullet. Always measure the impact in your specific use case.

Last updated:

Review Summary

4.38 out of 5
Average of 100+ ratings from Goodreads and Amazon.

Java Performance is highly praised as an essential, comprehensive guide for Java developers. Readers commend its in-depth coverage of JVM internals, garbage collection, and performance optimization techniques. While some find it challenging due to its technical density, many consider it a must-read for experienced developers. The book is noted for its practical examples, benchmarks, and up-to-date information on Java 7 and 8. Reviewers consistently rate it highly, comparing it favorably to other respected Java texts and recommending it for those seeking to enhance their understanding of Java performance.

Your rating:

About the Author

Scott Oaks is a highly regarded author in the field of Java programming and performance optimization. With extensive experience in software development, Oaks has established himself as an authority on Java internals and performance tuning. His writing style is praised for its clarity and depth, making complex topics accessible to readers. Oaks' work is recognized for its practical approach, combining theoretical knowledge with real-world examples and benchmarks. His expertise in JVM internals, garbage collection, and performance profiling is evident throughout his books, which are widely recommended by both novice and experienced Java developers.

Download PDF

To save this Java Performance summary for later, download the free PDF. You can print it out, or read offline at your convenience.
Download PDF
File size: 0.98 MB     Pages: 12

Download EPUB

To read this Java Performance summary on your e-reader device or app, download the free EPUB. The .epub digital book format is ideal for reading ebooks on phones, tablets, and e-readers.
Download EPUB
File size: 3.61 MB     Pages: 9
0:00
-0:00
1x
Dan
Andrew
Michelle
Lauren
Select Speed
1.0×
+
200 words per minute
Create a free account to unlock:
Requests: Request new book summaries
Bookmarks: Save your favorite books
History: Revisit books later
Ratings: Rate books & see your ratings
Unlock Unlimited Listening
🎧 Listen while you drive, walk, run errands, or do other activities
2.8x more books Listening Reading
Today: Get Instant Access
Listen to full summaries of 73,530 books. That's 12,000+ hours of audio!
Day 4: Trial Reminder
We'll send you a notification that your trial is ending soon.
Day 7: Your subscription begins
You'll be charged on Jan 25,
cancel anytime before.
Compare Features Free Pro
Read full text summaries
Summaries are free to read for everyone
Listen to summaries
12,000+ hours of audio
Unlimited Bookmarks
Free users are limited to 10
Unlimited History
Free users are limited to 10
What our users say
30,000+ readers
"...I can 10x the number of books I can read..."
"...exceptionally accurate, engaging, and beautifully presented..."
"...better than any amazon review when I'm making a book-buying decision..."
Save 62%
Yearly
$119.88 $44.99/year
$3.75/mo
Monthly
$9.99/mo
Try Free & Unlock
7 days free, then $44.99/year. Cancel anytime.
Settings
Appearance
Black Friday Sale 🎉
$20 off Lifetime Access
$79.99 $59.99
Upgrade Now →