OReilly java performance may 2014 ISBN 1449358454 - Pdf 42




Java Performance: The Definitive Guide
by Scott Oaks
Copyright © 2014 Scott Oaks. All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are
also available for most titles (http://my.safaribooksonline.com). For more information, contact our corporate/
institutional sales department: 800-998-9938 or [email protected].

Editor: Meghan Blanchette
Production Editor: Kristen Brown
Copyeditor: Becca Freed
Proofreader: Charles Roumeliotis
April 2014:

Indexer: Judith McConville
Cover Designer: Karen Montgomery
Interior Designer: David Futato
Illustrator: Rebecca Demarest

First Edition

Revision History for the First Edition:
2014-04-09: First release
See http://oreilly.com/catalog/errata.csp?isbn=9781449358457 for release details.
Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly
Media, Inc. Java Performance: The Definitive Guide, the image of saiga antelopes, and related trade dress are
trademarks of O’Reilly Media, Inc.

5
6
7
8
9
10

2. An Approach to Performance Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Test a Real Application
Microbenchmarks
Macrobenchmarks
Mesobenchmarks
Common Code Examples
Understand Throughput, Batching, and Response Time
Elapsed Time (Batch) Measurements
Throughput Measurements
Response Time Tests
Understand Variability
Test Early, Test Often
Summary

11
11
16
18
20
24
24
25
26

Summary

38
41
43
44
46
47
50
51
51
51
51
52
54
55
57
59
60
66
70
72

4. Working with the JIT Compiler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Just-in-Time Compilers: An Overview
Hot Spot Compilation
Basic Tunings: Client or Server (or Both)
Optimizing Startup
Optimizing Batch Operations
Optimizing Long-Running Applications

90
94
94
96
97
98
98
101
101


Summary

103

5. An Introduction to Garbage Collection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Garbage Collection Overview
Generational Garbage Collectors
GC Algorithms
Choosing a GC Algorithm
Basic GC Tuning
Sizing the Heap
Sizing the Generations
Sizing Permgen and Metaspace
Controlling Parallelism
Adaptive Sizing
GC Tools
Summary

105

140
145
148
149
150
157
159
159
163
171
173
174

7. Heap Memory Best Practices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Heap Analysis
Heap Histograms
Heap Dumps
Out of Memory Errors
Using Less Memory
Reducing Object Size
Lazy Initialization
Immutable and Canonical Objects
String Interning

177
178
179
184
188
188

Summary

223
224
225
226
227
230
230
234
236

9. Threading and Synchronization Performance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
Thread Pools and ThreadPoolExecutors
Setting the Maximum Number of Threads
Setting the Minimum Number of Threads
Thread Pool Task Sizes
Sizing a ThreadPoolExecutor
The ForkJoinPool
Automatic Parallelization
Thread Synchronization
Costs of Synchronization
Avoiding Synchronization
False Sharing
JVM Thread Tunings
Tuning Thread Stack Sizes
Biased Locking
Lock Spinning
Thread Priorities
Monitoring Threads and Locks

vi

|

Table of Contents

277
280
283


Enterprise Java Session Beans
Tuning EJB Pools
Tuning EJB Caches
Local and Remote Instances
XML and JSON Processing
Data Size
An Overview of Parsing and Marshalling
Choosing a Parser
XML Validation
Document Models
Java Object Models
Object Serialization
Transient Fields
Overriding Default Serialization
Compressing Serialized Data
Keeping Track of Duplicate Objects
Java EE Networking APIs
Sizing Data Transfers
Summary

Optimizing JPA Writes
Optimizing JPA Reads
JPA Caching
JPA Read-Only Entities
Summary

322
322
324
326
327
335
337
337
340
342
346
352
353

12. Java SE API Tips. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
Buffered I/O
Classloading
Random Numbers
Java Native Interface
Exceptions
String Performance

355
358

376
378
378
379
379
381
382
383
385

A. Summary of Tuning Flags. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397

viii

| Table of Contents


Preface

When O’Reilly first approached me about writing a book on Java performance tuning,
I was unsure. Java performance, I thought—aren’t we done with that? Yes, I still work
on performance of Java (and other) applications on a daily basis, but I like to think that
I spend most of my time dealing with algorithmic inefficiences and external system
bottlenecks rather than on anything directly related to Java tuning.
A moment’s reflection convinced me that I was (as usual) kidding myself. It is certainly
true that end-to-end system performance takes up a lot of my time, and that I sometimes
come across code that uses an O (n 2) algorithm when it could use one with O(log N)
performance. Still, it turns out that every day, I think about GC performance, or the
performance of the JVM compiler, or how to get the best performance from Java En‐

is still beneficial. Second is that environmental changes in computing seem to have
altered the performance concerns that engineers face today.
What’s changed in the past few years is that performance concerns have become bifur‐
cated. On the one hand, very large machines capabable of running JVMs with very large
heaps are now commonplace. The JVM has moved to address those concerns with a
new garbage collector (G1), which—as a new technology—requires a little more handtuning than traditional collectors. At the same time, cloud computing has renewed the
importance of small, single-CPU machines: you can go to Oracle or Amazon or a host
of other companies and very cheaply rent a single CPU machine to run a small appli‐
cation server. (You’re not actually getting a single-CPU machine: you’re getting a virtual
OS image on a very large machine, but the virtual OS is limited to using a single CPU.
From the perspective of Java, that turns out to be the same as single-CPU machine.) In
those environments, correctly managing small amounts of memory turns out to be quite
important.
The Java platform also continues to evolve. Each new edition of Java provides new
language features and new APIs that improve the productivity of developers—if not
always the performance of their applications. Best practice use of these language features
can help to differentiate between an application that sizzles, and one that plods along.
And the evolution of the platform brings up interesting performance questions: there
is no question that using JSON to exchange information between two programs is much
simpler than coming up with a highly optimized proprietary protocol. Saving time for
developers is a big win—but making sure that productivity win comes with a perfor‐
mance win (or at least breaks even) is the real goal.

Who Should (and Shouldn’t) Read This Book
This book is designed for performance engineers and developers who are looking to
understand how various aspects of the JVM and the Java APIs impact performance.
If it is late Sunday night, your site is going live Monday morning, and you’re looking for
a quick fix for performance issues, this is not the book for you.

x

the programming aspects of Java, I do spent a fair amount of time discussing programs,
including the sample programs used to provide a lot of the data points in the examples.
Still, if your primary interest is in the performance of the JVM itself—meaning how to
alter the behavior of the JVM without any coding—then large sections of this book
should still be beneficial to you. Feel free to skip over the coding parts and focus in on
the areas that interest you. And maybe along the way, you’ll pick up some insight into
how Java applications can affect JVM performance and start to suggest changes to de‐
velopers so they can make your performance-testing life easier.

Conventions Used in This Book
The following typographical conventions are used in this book:
Italic
Indicates new terms, URLs, email addresses, filenames, and file extensions.

Preface

|

xi


Constant width

Used for program listings, as well as within paragraphs to refer to program elements
such as variable or function names, databases, data types, environment variables,
statements, and keywords.
Constant width bold

Shows commands or other text that should be typed literally by the user.
Constant width italic

Scott Oaks (O’Reilly). Copyright 2014 Scott Oaks, 978-1-449-35845-7.”
If you feel your use of code examples falls outside fair use or the permission given above,
feel free to contact us at [email protected].

Safari® Books Online
Safari Books Online is an on-demand digital library that
delivers expert content in both book and video form from
the world’s leading authors in technology and business.
Technology professionals, software developers, web designers, and business and crea‐
tive professionals use Safari Books Online as their primary resource for research, prob‐
lem solving, learning, and certification training.
Safari Books Online offers a range of product mixes and pricing programs for organi‐
zations, government agencies, and individuals. Subscribers have access to thousands of
books, training videos, and prepublication manuscripts in one fully searchable database
from publishers like O’Reilly Media, Prentice Hall Professional, Addison-Wesley Pro‐
fessional, Microsoft Press, Sams, Que, Peachpit Press, Focal Press, Cisco Press, John
Wiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press, FT
Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, Course Technol‐
ogy, and dozens more. For more information about Safari Books Online, please visit us
online.

How to Contact Us
Please address comments and questions concerning this book to the publisher:
O’Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
800-998-9938 (in the United States or Canada)
707-829-0515 (international or local)
707-829-0104 (fax)
We have a web page for this book, where we list errata, examples, and any additional

my husband James for putting up with the long nights and those weekend dinners where
I was in a continual state of distraction.

xiv

| Preface


CHAPTER 1

Introduction

This is a book about the art and science of Java performance.
The science part of this statement isn’t surprising; discussions about performance in‐
clude lots of numbers and measurements and analytics. Most performance engineers
have a background in the sciences, and applying scientific rigor is a crucial part of
achieving maximum performance.
What about the art part? The notion that performance tuning is part art and part science
is hardly new, but it is rarely given explicit acknowledgment in performance discussions.
This is partly because the idea of “art” goes against our training.
Part of the reason is that what looks like art to some people is fundamentally based on
deep knowledge and experience. It is said that magic is indistinguishable from suffi‐
ciently advanced technologies, and certainly it is true that a cell phone would look
magical to a knight of the Round Table. Similarly, the work produced by a good per‐
formance engineer may look like art, but that art is really an application of deep knowl‐
edge, experience, and intuition.
This book cannot help with the experience and intuition part of that equation, but its
goal is to help with the deep knowledge—with the view that applying knowledge over
time will help you develop the skills needed to be a good Java performance engineer.
The goal is to give you an in-depth understanding of the performance aspects of the

quires visibility into what the application is doing, Chapter 3 provides an overview of
some of the tools available to monitor Java applications.
Then it is time to dive into performance, focusing first on common tuning aspects: justin-time compilation (Chapter 4) and garbage collection (Chapter 5 and Chapter 6). The
remaining chapters focus on best practice uses of various parts of the Java platform:
memory use with the Java heap (Chapter 7), native memory use (Chapter 8), thread
performance (Chapter 9), Java Enterprise Edition APIs (Chapter 10), JPA and JDBC
(Chapter 11), and some general Java SE API tips (Chapter 12).
Appendix A lists all the tuning flags discussed in this book, with cross-references to the
chapter where they are examined.

Platforms and Conventions
This book is based on the Oracle HotSpot Java Virtual Machine and the Java Platform,
Standard Edition (Java SE), versions 7 and 8. Within versions, Oracle provides update
releases periodically. For the most part, update releases provide only bug fixes; they
never provide new language features or changes to key functionality. However, update
releases do sometimes change the default value of tuning flags. Oracle will doubtless
provide update releases that postdate publication of this book, which is current as of
Java 7 update 40 and Java 8 (as of yet, there are no Java 8 update releases). When an

2

|

Chapter 1: Introduction


update release provides an important change to JVM behavior, the update release is
specified like this: 7u6 (Java 7 update 6).
Sections on Java Enterprise Edition (Java EE) are based on Java EE 7.
This book does not address the performance of previous releases of Java, though of

This is particularly true of tuning flags. All JVM implementations have one or more
garbage collectors, but the flags to tune each vendor’s GC implementation are productspecific. Thus, while the concepts of this book apply to any Java implementation, the

Platforms and Conventions

|

3


specific flags and recommendations apply only to Oracle’s standard (HotSpot-based)
JVM.
That caveat is applicable to earlier releases of the HotSpot JVM—flags and their default
values change from release to release. Rather than attempting to be comprehensive and
cover a variety of now-outdated versions, the information in this book covers only Java
7 (up through 7u40) and Java 8 (the initial release only) JVMs. It is possible that later
releases (e.g., a hypothetical 7u60) may slightly change some of this information. Always
consult the release notes for important changes.
At an API level, different JVM implementations are much more compatible, though
even then there might be subtle differences between the way a particular class is imple‐
mented in the Oracle HotSpot Java SE (or EE) platform and an alternate platform. The
classes must be functionally equivalent, but the actual implementation may change.
Fortunately, that is infrequent, and unlikely to drastically affect performance.
For the remainder of this book, the terms Java and JVM should be understood to refer
specifically to the Oracle HotSpot implementation. Strictly speaking, saying “The JVM
does not compile code upon first execution” is wrong; there are Java implementations
that do compile code the first time it is executed. But that shorthand is much easier than
continuing to write (and read) “The Oracle HotSpot JVM…”

JVM Tuning Flags

Client-class machines are any 32-bit JVM running on Microsoft Windows (regardless
of the number of CPUs on the machine), and any 32-bit JVM running on a machine
with one CPU (regardless of the operating system). All other machines (including all
64-bit JVMs) are considered server class.

The JVM that is downloaded from Oracle and OpenJDK sites is called the “product”
build of the JVM. When the JVM is built from source code, there are many different
builds that can be produced: debug builds, developer builds, and so on. These builds
often have additional functionality in them. In particular, developer builds include an
even larger set of tuning flags so that developers can experiment with the most minute
operations of various algorithms used by the JVM. Those flags are generally not con‐
sidered in this book.

The Complete Performance Story
This book is focused on how to best use the JVM and Java platform APIs so that pro‐
grams run faster, but there are many outside influences that affect performance. Those
influences pop up from time to time in the discussion, but because they are not specific
to Java, they are not necessarily discussed in detail. The performance of the JVM and
the Java platform is a small part of getting to fast performance.
Here are some of the outside influences that are at least as important as the Java tuning
topics covered in this book. The Java knowledge-based approach of this book comple‐
ments these influences, but many of them are beyond the scope of what we’ll discuss.

Write Better Algorithms
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.
Ultimately, the performance of an application is based on how well it is written. If the
program loops through all elements in an array, the JVM will optimize the array boundschecking so that the loop runs faster, and it may unroll the loop operations to provide
an additional speedup. But if the purpose of the loop is to find a specific item, no


since hardware improvements make it possible to run the new programs at acceptable
speeds.
Think what it would be like to run the Windows Aero interface on the same computer
that used to run Windows 95. My favorite computer ever was a Mac Quadra 950, but it
couldn’t run Mac OS X (and it if did, it would be so very, very slow compared to Mac
OS 7.5). On a smaller level, it may seem that Firefox 23.0 is faster than Firefox 22.0, but
those are essentially minor release versions. With its tabbed browsing and synced scroll‐
ing and security features, Firefox is far more powerful than Mosaic ever was, but Mosaic
can load basic HTML files located on my hard disk about 50% faster than Firefox 23.0.
Of course, Mosaic cannot load actual URLs from almost any popular website; it is no
longer possible to use Mosaic as a primary browser. That is also part of the general point
here: particularly between minor releases, code may be optimized and run faster. As
performance engineers, that’s what we can focus on, and if we are good at our job, we
can win the battle. That is a good and valuable thing; my argument isn’t that we shouldn’t
work to improve the performance of existing applications.

6

|

Chapter 1: Introduction


But the irony remains: as new features are added and new standards adopted—which
is a requirement to match competing programs—programs can be expected to get larger
and slower.

I think of this as the “death by 1,000 cuts” principle. Developers will argue that they are
just adding a very small feature and it will take no time at all (especially if the feature
isn’t used). And then other developers on the same project make the same claim, and


The Complete Performance Story

|

7


This code does a string concatenation that is likely unnecessary, since the message won’t
be logged unless the logging level is set quite high. If the message isn’t printed, then
unnecessary calls are also made to the calcX() and calcY() methods. Experienced Java
developers will reflexively reject that; some IDEs (such as NetBeans) will even flag the
code and suggest it be changed. (Tools aren’t perfect, though: NetBeans will flag the
string concatenation, but the suggested improvement retains the unneeded method
calls.)
This logging code is better written like this:
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE,
"I am here, and the value of X is {} and Y is {}",
new Object[]{calcX(), calcY()});
}

This avoids the string concatenation altogether (the message format isn’t necessarily
more efficient, but it is cleaner), and there are no method calls or allocation of the object
array unless logging has been enabled.
Writing code in this way is still clean and easy to read; it took no more effort than writing
the original code. Well, OK, it required a few more keystrokes and an extra line of logic.
But it isn’t the type of premature optimization that should be avoided; it’s the kind of
choice that good coders learn to make. Don’t let out-of-context dogma from pioneering
heroes prevent you from thinking about the code you are writing.

server, and testing showed that the requests sent to the server took longer and longer
over time. Applying Occam’s Razor (see the next tip) led me to consider all aspects of
the application server that might be causing the issue.
After those were ruled out, the performance issue remained, and there was no backend
database on which to place the blame. The next most likely issue, therefore, was the test
harness, and some profiling determined that the load generator—Apache JMeter—was
the source of the regression: it was keeping every response in a list, and when a new
response came in, it processed the entire list in order to calculate the 90th% response
time (if that term is unfamiliar, see Chapter 2).
Performance issues can be caused by any part of the entire system where an application
is deployed. Common case analysis says to consider the newest part of the system first
(which is often the application in the JVM), but be prepared to look at every possible
component of the environment.

On the other hand, don’t overlook that initial analysis. If the database is the bottleneck
(and here’s a hint: it is), then tuning the Java application accessing the database won’t
help overall performance at all. In fact, it might be counterproductive. As a general rule,
when load is increased into a system that is overburdened, performance of that system
gets worse. If something is changed in the Java application that makes it more efficient
—which only increases the load on an already-overloaded database—overall perfor‐
mance may actually go down. The danger there is then reaching the incorrect conclusion
that the particular JVM improvement shouldn’t be used.
This principle—that increasing load to a component in a system that is performing badly
will make the entire system slower—isn’t confined to a database. It applies when load is
added to an application server that is CPU-bound, or if more threads start accessing a
lock that already has threads waiting for it, or any of a number of other scenarios. An
extreme example of this that involves only the JVM is shown in Chapter 9.

Optimize for the Common Case
It is tempting—particularly given the “death by 1,000 cuts” syndrome—to treat all per‐


Nhờ tải bản gốc

Tài liệu, ebook tham khảo khác

Music ♫

Copyright: Tài liệu đại học © DMCA.com Protection Status