1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
|
page.title=Designing for Performance
@jd:body
<p>An Android application should be fast. Well, it's probably more accurate to
say that it should be <em>efficient</em>. That is, it should execute as
efficiently as possible in the mobile device environment, with its limited
computing power and data storage, smaller screen, and constrained battery life.
<p>As you develop your application, keep in mind that, while the application may
perform well enough in your emulator, running on your dual-core development
computer, it will not perform that well when run a mobile device — even
the most powerful mobile device can't match the capabilities of a typical
desktop system. For that reason, you should strive to write efficient code, to
ensure the best possible performance on a variety of mobile devices.</p>
<p>Generally speaking, writing fast or efficient code means keeping memory
allocations to a minimum, writing tight code, and avoiding certain language and
programming idioms that can subtly cripple performance. In object-oriented
terms, most of this work takes place at the <em>method</em> level, on the order of
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>
<li><a href="#prefer_static">Prefer Static Over Virtual</a></li>
<li><a href="#internal_get_set">Avoid Internal Getters/Setters</a></li>
<li><a href="#cache_fields">Cache Field Lookups</a></li>
<li><a href="#use_final">Declare Constants Final</a></li>
<li><a href="#foreach">Use Enhanced For Loop Syntax With Caution</a></li>
<li><a href="#avoid_enums">Avoid Enums</a></li>
<li><a href="#package_inner">Use Package Scope with Inner Classes</a></li>
<li><a href="#avoidfloat">Avoid Float</a> </li>
<li><a href="#samples">Some Sample Performance Numbers</a> </li>
<li><a href="#closing_notes">Closing Notes</a></li>
</ul>
<a name="intro" id="intro"></a>
<h2>Introduction</h2>
<p>There are two basic rules for resource-constrained systems:</p>
<ul>
<li>Don't do work that you don't need to do.</li>
<li>Don't allocate memory if you can avoid it.</li>
</ul>
<p>All the tips below follow from these two basic tenets.</p>
<p>Some would argue that much of the advice on this page amounts to "premature
optimization." While it's true that micro-optimizations sometimes make it
harder to develop efficient data structures and algorithms, on embedded
devices like handsets you often simply have no choice. For instance, if you
bring your assumptions about VM performance on desktop machines to Android,
you're quite likely to write code that exhausts system memory. This will bring
your application to a crawl — let alone what it will do to other programs
running on the system!</p>
<p>That's why these guidelines are important. Android's success depends on
the user experience that your applications provide, and that user experience
depends in part on whether your code is responsive and snappy, or slow and
aggravating. Since all our applications will run on the same devices, we're
all in this together, in a way. Think of this document as like the rules of
the road you had to learn when you got your driver's license: things run
smoothly when everybody follows them, but when you don't, you get your car
smashed up.</p>
<p>Before we get down to brass tacks, a brief observation: nearly all issues
described below are valid whether or not the VM features a JIT compiler. If I
have two methods that accomplish the same thing, and the interpreted execution
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 — 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 — 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—including blind stupidity.</p>
<p>—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>—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 — that is, not until you have a
perfectly clear and unoptimized solution. </li>
</ul>
<p>—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 — 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>—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>
<p>Object creation is never free. A generational GC with per-thread allocation
pools for temporary objects can make allocation cheaper, but allocating memory
is always more expensive than not allocating memory.</p>
<p>If you allocate objects in a user interface loop, you will force a periodic
garbage collection, creating little "hiccups" in the user experience.</p>
<p>Thus, you should avoid creating object instances you don't need to. Some
examples of things that can help:</p>
<ul>
<li>When extracting strings from a set of input data, try
to return a substring of the original data, instead of creating a copy.
You will create a new String object, but it will share the char[]
with the data.</li>
<li>If you have a method returning a string, and you know that its result
will always be appended to a StringBuffer anyway, change your signature
and implementation so that the function does the append directly,
instead of creating a short-lived temporary object.</li>
</ul>
<p>A somewhat more radical idea is to slice up multidimensional arrays into parallel
single one-dimension arrays:</p>
<ul>
<li>An array of ints is a much better than an array of Integers,
but this also generalizes to the fact that two parallel arrays of ints
are also a <strong>lot</strong> more efficient than an array of (int,int)
objects. The same goes for any combination of primitive types.</li>
<li>If you need to implement a container that stores tuples of (Foo,Bar)
objects, try to remember that two parallel Foo[] and Bar[] arrays are
generally much better than a single array of custom (Foo,Bar) objects.
(The exception to this, of course, is when you're designing an API for
other code to access; in those cases, it's usually better to trade
correct API design for a small hit in speed. But in your own internal
code, you should try and be as efficient as possible.)</li>
</ul>
<p>Generally speaking, avoid creating short-term temporary objects if you
can. Fewer objects created mean less-frequent garbage collection, which has
a direct impact on user experience.</p>
<a name="native_methods" id="native_methods"></a>
<h2>Use Native Methods</h2>
<p>When processing strings, don't hesitate to use specialty methods like
String.indexOf(), String.lastIndexOf(), and their cousins. These are typically
implemented in C/C++ code that easily runs 10-100x faster than doing the same
thing in a Java loop.</p>
<p>The flip side of that advice is that punching through to a native
method is more expensive than calling an interpreted method. Don't use native
methods for trivial computation, if you can avoid it.</p>
<a name="prefer_virtual" id="prefer_virtual"></a>
<h2>Prefer Virtual Over Interface</h2>
<p>Suppose you have a HashMap object. You can declare it as a HashMap or as
a generic Map:</p>
<pre>Map myMap1 = new HashMap();
HashMap myMap2 = new HashMap();</pre>
<p>Which is better?</p>
<p>Conventional wisdom says that you should prefer Map, because it
allows you to change the underlying implementation to anything that
implements the Map interface. Conventional wisdom is correct for
conventional programming, but isn't so great for embedded systems. Calling
through an interface reference can take 2x longer than a virtual
method call through a concrete reference.</p>
<p>If you have chosen a HashMap because it fits what you're doing, there
is little value in calling it a Map. Given the availability of
IDEs that refactor your code for you, there's not much value in calling
it a Map even if you're not sure where the code is headed. (Again, though,
public APIs are an exception: a good API usually trumps small performance
concerns.)</p>
<a name="prefer_static" id="prefer_static"></a>
<h2>Prefer Static Over Virtual</h2>
<p>If you don't need to access an object's fields, make your method static. It can
be called faster, because it doesn't require a virtual method table
indirection. It's also good practice, because you can tell from the method
signature that calling the method can't alter the object's state.</p>
<a name="internal_get_set" id="internal_get_set"></a>
<h2>Avoid Internal Getters/Setters</h2>
<p>In native languages like C++ it's common practice to use getters (e.g.
<code>i = getCount()</code>) instead of accessing the field directly (<code>i
= mCount</code>). This is an excellent habit for C++, because the compiler can
usually inline the access, and if you need to restrict or debug field access
you can add the code at any time.</p>
<p>On Android, this is a bad idea. Virtual method calls are expensive,
much more so than instance field lookups. It's reasonable to follow
common object-oriented programming practices and have getters and setters
in the public interface, but within a class you should always access
fields directly.</p>
<a name="cache_fields" id="cache_fields"></a>
<h2>Cache Field Lookups</h2>
<p>Accessing object fields is much slower than accessing local variables.
Instead of writing:</p>
<pre>for (int i = 0; i < this.mCount; i++)
dumpItem(this.mItems[i]);</pre>
<p>You should write:</p>
<pre> int count = this.mCount;
Item[] items = this.mItems;
for (int i = 0; i < count; i++)
dumpItems(items[i]);
</pre>
<p>(We're using an explicit "this" to make it clear that these are
member variables.)</p>
<p>A similar guideline is never call a method in the second clause of a "for"
statement. For example, the following code will execute the getCount() method
once per iteration, which is a huge waste when you could have simply cached
the value as an int:</p>
<pre>for (int i = 0; i < this.getCount(); i++)
dumpItems(this.getItem(i));
</pre>
<p>It's also usually a good idea to create a local variable if you're going to be
accessing an instance field more than once. For example:</p>
<pre>
protected void drawHorizontalScrollBar(Canvas canvas, int width, int height) {
if (isHorizontalScrollBarEnabled()) {
int size = <strong>mScrollBar</strong>.getSize(<em>false</em>);
if (size <= 0) {
size = mScrollBarSize;
}
<strong>mScrollBar</strong>.setBounds(0, <em>height</em> - size, width, height);
<strong>mScrollBar</strong>.setParams(
computeHorizontalScrollRange(),
computeHorizontalScrollOffset(),
computeHorizontalScrollExtent(), <em>false</em>);
<strong>mScrollBar</strong>.draw(canvas);
}
}</pre>
<p>That's four separate lookups of the member field <code>mScrollBar</code>.
By caching mScrollBar in a local stack variable, the four member field lookups
become four stack variable references, which are much more efficient.</p>
<p>Incidentally, method arguments have the same performance characteristics
as local variables.</p>
<a name="use_final" id="use_final"></a>
<h2>Declare Constants Final</h2>
<p>Consider the following declaration at the top of a class:</p>
<pre>static int intVal = 42;
static String strVal = "Hello, world!";</pre>
<p>The compiler generates a class initializer method, called
<code><clinit></code>, that is executed when the class is first used.
The method stores the value 42 into <code>intVal</code>, and extracts a
reference from the classfile string constant table for <code>strVal</code>.
When these values are referenced later on, they are accessed with field
lookups.</p>
<p>We can improve matters with the "final" keyword:</p>
<pre>static final int intVal = 42;
static final String strVal = "Hello, world!";</pre>
<p>The class no longer requires a <code><clinit></code> method,
because the constants go into classfile static field initializers, which are
handled directly by the VM. Code accessing <code>intVal</code> will use
the integer value 42 directly, and accesses to <code>strVal</code> will
use a relatively inexpensive "string constant" instruction instead of a
field lookup.</p>
<p>Declaring a method or class "final" does not confer any immediate
performance benefits, but it does allow certain optimizations. For example, if
the compiler knows that a "getter" method can't be overridden by a sub-class,
it can inline the method call.</p>
<p>You can also declare local variables final. However, this has no definitive
performance benefits. For local variables, only use "final" if it makes the
code clearer (or you have to, e.g. for use in an anonymous inner class).</p>
<a name="foreach" id="foreach"></a>
<h2>Use Enhanced For Loop Syntax With Caution</h2>
<p>The enhanced for loop (also sometimes known as "for-each" loop) can be used for collections that implement the Iterable interface.
With these objects, an iterator is allocated to make interface calls
to hasNext() and next(). With an ArrayList, you're better off walking through
it directly, but for other collections the enhanced for loop syntax will be equivalent
to explicit iterator usage.</p>
<p>Nevertheless, the following code shows an acceptable use of the enhanced for loop:</p>
<pre>public class Foo {
int mSplat;
static Foo mArray[] = new Foo[27];
public static void zero() {
int sum = 0;
for (int i = 0; i < mArray.length; i++) {
sum += mArray[i].mSplat;
}
}
public static void one() {
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; i++) {
sum += localArray[i].mSplat;
}
}
public static void two() {
int sum = 0;
for (Foo a: mArray) {
sum += a.mSplat;
}
}
}</pre>
<p><strong>zero()</strong> retrieves the static field twice and gets the array
length once for every iteration through the loop.</p>
<p><strong>one()</strong> pulls everything out into local variables, avoiding
the lookups.</p>
<p><strong>two()</strong> uses the enhanced for loop syntax introduced in version 1.5 of
the Java programming language. The code generated by the compiler takes care
of copying the array reference and the array length to local variables, making
it a good choice for walking through all elements of an array. It does
generate an extra local load/store in the main loop (apparently preserving
"a"), making it a teensy bit slower and 4 bytes longer than one().</p>
<p>To summarize all that a bit more clearly: enhanced for loop syntax performs well
with arrays, but be cautious when using it with Iterable objects since there is
additional object creation.</p>
<a name="avoid_enums" id="avoid_enums"></a>
<h2>Avoid Enums</h2>
<p>Enums are very convenient, but unfortunately can be painful when size
and speed matter. For example, this:</p>
<pre>public class Foo {
public enum Shrubbery { GROUND, CRAWLING, HANGING }
}</pre>
<p>turns into a 900 byte .class file (Foo$Shrubbery.class). On first use, the
class initializer invokes the <init> method on objects representing each
of the enumerated values. Each object gets its own static field, and the full
set is stored in an array (a static field called "$VALUES"). That's a lot of
code and data, just for three integers.</p>
<p>This:</p>
<pre>Shrubbery shrub = Shrubbery.GROUND;</pre>
<p>causes a static field lookup. If "GROUND" were a static final int,
the compiler would treat it as a known constant and inline it.</p>
<p>The flip side, of course, is that with enums you get nicer APIs and
some compile-time value checking. So, the usual trade-off applies: you should
by all means use enums for public APIs, but try to avoid them when performance
matters.</p>
<p>In some circumstances it can be helpful to get enum integer values
through the <code>ordinal()</code> method. For example, replace:</p>
<pre>for (int n = 0; n < list.size(); n++) {
if (list.items[n].e == MyEnum.VAL_X)
// do stuff 1
else if (list.items[n].e == MyEnum.VAL_Y)
// do stuff 2
}</pre>
<p>with:</p>
<pre> int valX = MyEnum.VAL_X.ordinal();
int valY = MyEnum.VAL_Y.ordinal();
int count = list.size();
MyItem items = list.items();
for (int n = 0; n < count; n++)
{
int valItem = items[n].e.ordinal();
if (valItem == valX)
// do stuff 1
else if (valItem == valY)
// do stuff 2
}</pre>
<p>In some cases, this will be faster, though this is not guaranteed.</p>
<a name="package_inner" id="package_inner"></a>
<h2>Use Package Scope with Inner Classes</h2>
<p>Consider the following class definition:</p>
<pre>public class Foo {
private int mValue;
public void run() {
Inner in = new Inner();
mValue = 27;
in.stuff();
}
private void doStuff(int value) {
System.out.println("Value is " + value);
}
private class Inner {
void stuff() {
Foo.this.doStuff(Foo.this.mValue);
}
}
}</pre>
<p>The key things to note here are that we define an inner class (Foo$Inner)
that directly accesses a private method and a private instance field
in the outer class. This is legal, and the code prints "Value is 27" as
expected.</p>
<p>The problem is that Foo$Inner is technically (behind the scenes) a totally
separate class, which makes direct access to Foo's private
members illegal. To bridge that gap, the compiler generates a
couple of synthetic methods:</p>
<pre>/*package*/ static int Foo.access$100(Foo foo) {
return foo.mValue;
}
/*package*/ static void Foo.access$200(Foo foo, int value) {
foo.doStuff(value);
}</pre>
<p>The inner-class code calls these static methods whenever it needs to
access the "mValue" field or invoke the "doStuff" method in the outer
class. What this means is that the code above really boils down to a case
where you're accessing member fields through accessor methods instead of
directly. Earlier we talked about how accessors are slower than direct field
accesses, so this is an example of a certain language idiom resulting in an
"invisible" performance hit.</p>
<p>We can avoid this problem by declaring fields and methods accessed
by inner classes to have package scope, rather than private scope.
This runs faster and removes the overhead of the generated methods.
(Unfortunately it also means the fields could be accessed directly by other
classes in the same package, which runs counter to the standard OO
practice of making all fields private. Once again, if you're
designing a public API you might want to carefully consider using this
optimization.)</p>
<a name="avoidfloat" id="avoidfloat"></a>
<h2>Avoid Float</h2>
<p>Before the release of the Pentium CPU, it was common for game authors to do
as much as possible with integer math. With the Pentium, the floating point
math co-processor became a built-in feature, and by interleaving integer and
floating-point operations your game would actually go faster than it would
with purely integer math. The common practice on desktop systems is to use
floating point freely.</p>
<p>Unfortunately, embedded processors frequently do not have hardware floating
point support, so all operations on "float" and "double" are performed in
software. Some basic floating point operations can take on the order of a
millisecond to complete.</p>
<p>Also, even for integers, some chips have hardware multiply but lack
hardware divide. In such cases, integer division and modulus operations are
performed in software — something to think about if you're designing a
hash table or doing lots of math.</p>
<a name="samples" id="samples"></a>
<h2>Some Sample Performance Numbers</h2>
<p>To illustrate some of our ideas, here is a table listing the approximate
run times for a few basic actions. Note that these values should NOT be taken
as absolute numbers: they are a combination of CPU and wall clock time, and
will change as improvements are made to the system. However, it is worth
noting how these values apply relative to each other — for example,
adding a member variable currently takes about four times as long as adding a
local variable.</p>
<table>
<tr>
<th>Action</th>
<th>Time</th>
</tr>
<tr>
<td>Add a local variable </td>
<td>1</td>
</tr>
<tr class="alt">
<td>Add a member variable </td>
<td>4</td>
</tr>
<tr>
<td>Call String.length()</td>
<td>5</td>
</tr>
<tr class="alt">
<td>Call empty static native method</td>
<td>5</td>
</tr>
<tr>
<td>Call empty static method </td>
<td>12</td>
</tr>
<tr class="alt">
<td>Call empty virtual method </td>
<td>12.5</td>
</tr>
<tr>
<td>Call empty interface method </td>
<td>15</td>
</tr>
<tr class="alt">
<td>Call Iterator:next() on a HashMap </td>
<td>165</td>
</tr>
<tr>
<td>Call put() on a HashMap</td>
<td>600</td>
</tr>
<tr class="alt">
<td>Inflate 1 View from XML </td>
<td>22,000</td>
</tr>
<tr>
<td>Inflate 1 LinearLayout containing 1 TextView </td>
<td>25,000</td>
</tr>
<tr class="alt">
<td>Inflate 1 LinearLayout containing 6 View objects </td>
<td>100,000</td>
</tr>
<tr>
<td>Inflate 1 LinearLayout containing 6 TextView objects </td>
<td>135,000</td>
</tr>
<tr class="alt">
<td>Launch an empty activity </td>
<td>3,000,000</td>
</tr>
</table>
<a name="closing_notes" id="closing_notes"></a>
<h2>Closing Notes</h2>
<p>The best way to write good, efficient code for embedded systems is to
understand what the code you write really does. If you really want to allocate
an iterator, by all means use enhanced for loop syntax on a List; just make it a
deliberate choice, not an inadvertent side effect.</p>
<p>Forewarned is forearmed! Know what you're getting into! Insert your
favorite maxim here, but always think carefully about what your code is doing,
and be on the lookout for ways to speed it up.</p>
|