summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/practices/design
diff options
context:
space:
mode:
authorDirk Dougherty <ddougherty@google.com>2010-01-05 17:03:39 -0800
committerDirk Dougherty <ddougherty@google.com>2010-01-07 12:05:01 -0800
commit4e7db256878bbf2058fa7d1bf07ddbe1c7206103 (patch)
tree06e37450ddc5084b46b2840054e3a3cd8d0e3a4f /docs/html/guide/practices/design
parenteb5ffc239b6482b9c1e046f6f5872187043d852c (diff)
downloadframeworks_base-4e7db256878bbf2058fa7d1bf07ddbe1c7206103.zip
frameworks_base-4e7db256878bbf2058fa7d1bf07ddbe1c7206103.tar.gz
frameworks_base-4e7db256878bbf2058fa7d1bf07ddbe1c7206103.tar.bz2
SDK doc change: add "Optimizing Judiciously" excerpt to best practices. Clean up blockquote usage in other files.
Bug: 2160782 Change-Id: I537194ecddc53d4f0e8456ce958ae8db6f521593
Diffstat (limited to 'docs/html/guide/practices/design')
-rw-r--r--docs/html/guide/practices/design/performance.jd175
1 files changed, 175 insertions, 0 deletions
diff --git a/docs/html/guide/practices/design/performance.jd b/docs/html/guide/practices/design/performance.jd
index 1eef342..ec34ac9 100644
--- a/docs/html/guide/practices/design/performance.jd
+++ b/docs/html/guide/practices/design/performance.jd
@@ -22,6 +22,7 @@ actual lines of code, loops, and so on.</p>
<p>This document covers these topics: </p>
<ul>
<li><a href="#intro">Introduction</a></li>
+ <li><a href="#optimize_judiciously">Optimize Judiciously</a></li>
<li><a href="#object_creation">Avoid Creating Objects</a></li>
<li><a href="#native_methods">Use Native Methods</a></li>
<li><a href="#prefer_virtual">Prefer Virtual Over Interface</a></li>
@@ -74,6 +75,180 @@ of foo() is faster than bar(), then the compiled version of foo() will
probably be as fast or faster than compiled bar(). It is unwise to rely on a
compiler to "save" you and make your code fast enough.</p>
+<h2 id="optimize_judiciously">Optimize Judiciously</h2>
+
+<p>As you get started thinking about how to design your application, consider
+the cautionary points about optimization that Josh Bloch makes in his book
+<em>Effective Java</em>. Here's "Item 47: Optimize Judiciously", excerpted from
+the latest edition of the book with permission. Although Josh didn't have
+Android application development in mind when writing this section &mdash; for
+example, the <code style="color:black">java.awt.Component</code> class
+referenced is not available in Android, and Android uses the
+Dalvik VM, rather than a standard JVM &mdash; his points are still valid. </p>
+
+<blockquote>
+
+<p>There are three aphorisms concerning optimization that everyone should know.
+They are perhaps beginning to suffer from overexposure, but in case you aren't
+yet familiar with them, here they are:</p>
+
+<div style="padding-left:3em;padding-right:4em;">
+
+<p style="margin-bottom:.5em;">More computing sins are committed in the name of
+efficiency (without necessarily achieving it) than for any other single
+reason&mdash;including blind stupidity.</p>
+<p>&mdash;William A. Wulf <span style="font-size:80%;"><sup>1</sup></span></p>
+
+<p style="margin-bottom:.5em;">We should forget about small efficiencies, say
+about 97% of the time: premature optimization is the root of all evil. </p>
+<p>&mdash;Donald E. Knuth <span style="font-size:80%;"><sup>2</sup></span></p>
+
+
+<p style="margin-bottom:.5em;">We follow two rules in the matter of optimization:</p>
+<ul style="margin-bottom:0">
+<li>Rule 1. Don't do it.</li>
+<li>Rule 2 (for experts only). Don't do it yet &mdash; that is, not until you have a
+perfectly clear and unoptimized solution. </li>
+</ul>
+<p>&mdash;M. A. Jackson <span style="font-size:80%;"><sup>3</sup></span></p>
+</div>
+
+<p>All of these aphorisms predate the Java programming language by two decades.
+They tell a deep truth about optimization: it is easy to do more harm than good,
+especially if you optimize prematurely. In the process, you may produce software
+that is neither fast nor correct and cannot easily be fixed.</p>
+
+<p>Don't sacrifice sound architectural principles for performance.
+<strong>Strive to write good programs rather than fast ones.</strong> If a good
+program is not fast enough, its architecture will allow it to be optimized. Good
+programs embody the principle of <em>information hiding</em>: where possible,
+they localize design decisions within individual modules, so individual
+decisions can be changed without affecting the remainder of the system (Item
+13).</p>
+
+<p>This does <em>not</em> mean that you can ignore performance concerns until
+your program is complete. Implementation problems can be fixed by later
+optimization, but pervasive architectural flaws that limit performance can be
+impossible to fix without rewriting the system. Changing a fundamental facet of
+your design after the fact can result in an ill-structured system that is
+difficult to maintain and evolve. Therefore you must think about performance
+during the design process.</p>
+
+<p><strong>Strive to avoid design decisions that limit performance.</strong> The
+components of a design that are most difficult to change after the fact are
+those specifying interactions between modules and with the outside world. Chief
+among these design components are APIs, wire-level protocols, and persistent
+data formats. Not only are these design components difficult or impossible to
+change after the fact, but all of them can place significant limitations on the
+performance that a system can ever achieve.</p>
+
+<p><strong>Consider the performance consequences of your API design
+decisions.</strong> Making a public type mutable may require a lot of needless
+defensive copying (Item 39). Similarly, using inheritance in a public class
+where composition would have been appropriate ties the class forever to its
+superclass, which can place artificial limits on the performance of the subclass
+(Item 16). As a final example, using an implementation type rather than an
+interface in an API ties you to a specific implementation, even though faster
+implementations may be written in the future (Item 52).</p>
+
+<p>The effects of API design on performance are very real. Consider the <code
+style="color:black">getSize</code> method in the <code
+style="color:black">java.awt.Component</code> class. The decision that this
+performance-critical method was to return a <code
+style="color:black">Dimension</code> instance, coupled with the decision that
+<code style="color:black">Dimension</code> instances are mutable, forces any
+implementation of this method to allocate a new <code
+style="color:black">Dimension</code> instance on every invocation. Even though
+allocating small objects is inexpensive on a modern VM, allocating millions of
+objects needlessly can do real harm to performance.</p>
+
+<p>In this case, several alternatives existed. Ideally, <code
+style="color:black">Dimension</code> should have been immutable (Item 15);
+alternatively, the <code style="color:black">getSize</code> method could have
+been replaced by two methods returning the individual primitive components of a
+<code style="color:black">Dimension</code> object. In fact, two such methods
+were added to the Component API in the 1.2 release for performance reasons.
+Preexisting client code, however, still uses the <code
+style="color:black">getSize</code> method and still suffers the performance
+consequences of the original API design decisions.</p>
+
+<p>Luckily, it is generally the case that good API design is consistent with
+good performance. <strong>It is a very bad idea to warp an API to achieve good
+performance.</strong> The performance issue that caused you to warp the API may
+go away in a future release of the platform or other underlying software, but
+the warped API and the support headaches that come with it will be with you for
+life.</p>
+
+<p>Once you've carefully designed your program and produced a clear, concise,
+and well-structured implementation, <em>then</em> it may be time to consider
+optimization, assuming you're not already satisfied with the performance of the
+program.</p>
+
+<p>Recall that Jackson's two rules of optimization were "Don't do it," and "(for
+experts only). Don't do it yet." He could have added one more: <strong>measure
+performance before and after each attempted optimization.</strong> You may be
+surprised by what you find. Often, attempted optimizations have no measurable
+effect on performance; sometimes, they make it worse. The main reason is that
+it's difficult to guess where your program is spending its time. The part of the
+program that you think is slow may not be at fault, in which case you'd be
+wasting your time trying to optimize it. Common wisdom says that programs spend
+80 percent of their time in 20 percent of their code.</p>
+
+<p>Profiling tools can help you decide where to focus your optimization efforts.
+Such tools give you runtime information, such as roughly how much time each
+method is consuming and how many times it is invoked. In addition to focusing
+your tuning efforts, this can alert you to the need for algorithmic changes. If
+a quadratic (or worse) algorithm lurks inside your program, no amount of tuning
+will fix the problem. You must replace the algorithm with one that is more
+efficient. The more code in the system, the more important it is to use a
+profiler. It's like looking for a needle in a haystack: the bigger the haystack,
+the more useful it is to have a metal detector. The JDK comes with a simple
+profiler and modern IDEs provide more sophisticated profiling tools.</p>
+
+<p>The need to measure the effects of attempted optimization is even greater on
+the Java platform than on more traditional platforms, because the Java
+programming language does not have a strong <em>performance model</em>. The
+relative costs of the various primitive operations are not well defined. The
+"semantic gap" between what the programmer writes and what the CPU executes is
+far greater than in traditional statically compiled languages, which makes it
+very difficult to reliably predict the performance consequences of any
+optimization. There are plenty of performance myths floating around that turn
+out to be half-truths or outright lies.</p>
+
+<p>Not only is Java's performance model ill-defined, but it varies from JVM
+implementation to JVM implementation, from release to release, and from
+processor to processor. If you will be running your program on multiple JVM
+implementations or multiple hardware platforms, it is important that you measure
+the effects of your optimization on each. Occasionally you may be forced to make
+trade-offs between performance on different JVM implementations or hardware
+platforms.</p>
+
+<p>To summarize, do not strive to write fast programs &mdash; strive to write
+good ones; speed will follow. Do think about performance issues while you're
+designing systems and especially while you're designing APIs, wire-level
+protocols, and persistent data formats. When you've finished building the
+system, measure its performance. If it's fast enough, you're done. If not,
+locate the source of the problems with the aid of a profiler, and go to work
+optimizing the relevant parts of the system. The first step is to examine your
+choice of algorithms: no amount of low-level optimization can make up for a poor
+choice of algorithm. Repeat this process as necessary, measuring the performance
+after every change, until you're satisfied.</p>
+
+<p>&mdash;Excerpted from Josh Bloch's <em>Effective Java</em>, Second Ed.
+(Addison-Wesley, 2008).</em></p>
+
+<p style="font-size:80%;margin-bottom:0;"><sup>1</sup> Wulf, W. A Case Against
+the GOTO. <em>Proceedings of the 25th ACM National
+Conference</em> 2 (1972): 791–797.</p>
+<p style="font-size:80%;margin-bottom:0;"><sup>2</sup> Knuth, Donald. Structured
+Programming with go to Statements. <em>Computing
+Surveys 6</em> (1974): 261–301.</p>
+<p style="font-size:80%"><sup>3</sup> Jackson, M. A. <em>Principles of Program
+Design</em>, Academic Press, London, 1975.
+ISBN: 0123790506.</p>
+
+</blockquote>
+
<a name="object_creation"></a>
<h2>Avoid Creating Objects</h2>