Java Performance Tuning
Java(TM) - see bottom of page
Our valued sponsors who help make this site possible
JProfiler: Get rid of your performance problems and memory leaks!
Training online: Threading Essentials course
Tips May 2008
Get rid of your performance problems and memory leaks!
Get rid of your performance problems and memory leaks!
Back to newsletter 090 contents
The Law of Cretan Driving (Page last updated February 2008, Added 2008-05-28, Author Dr. Heinz M. Kabutz, Publisher The Java Specialists' Newsletter). Tips:
- Declare shared 64-bit values (double & long) as volatile or synchronize access and update to them, as updates can take two operations.
- Too much synchronization causes contention. You can spot this when an increase in CPUs does not improve performance.
- Not enough synchronization can lead to race conditions and corrupt data.
- Without synchronization, fields can get written earlier than expected, and changes to shared fields might not be visible when you might have expected.
Hands-off load testing (Page last updated April 2008, Added 2008-05-28, Author Paul Duvall, Publisher IBM). Tips:
- Some performance questions to ask: How many concurrent users can access your software system? How much data can be loaded without performance degradation? What are your system's throughput requirements? How often are these requirements tested?
- Aim to run load tests as part of a daily scheduled and automated build to validate that load and performance requirements are being continually met.
- Running performance tests as part of a scheduled build lets you: Execute load tests at any time; Detect and resolve load and performance problems early in the development process; Monitor the latest load- and performance-test reports from your build server; Reduce bottlenecks and errors that can occur when you depend on a single person to configure and run the tests.
- [Article demonstrates how to run Apache Jmeter load testing client]
Big Games, Small Screens (Page last updated November 2007, Added 2008-05-28, Author Mark Callow, Paul Beardow, David Brittain, Publisher ACM Queue). Tips:
- There are fundamental differences between the cellphone market and consoles and handheld gaming devices: the number of delivery platforms; the severe constraints of the devices; small screens whose orientation can be changed; limited input controls; the need to deal with other tasks; the nonphysical delivery mechanism; and the variations in handset performance and input capability. The number and types of devices are also constantly changing, in a 12-month development cycle many new handsets can emerge.
- Mobile games are typified by short bursts of intense activity, rather than length of play and numbers of levels.
- Multiple platforms and leads to placing great emphasis on up-front planning and design of a game. Right from the start, the developer needs to consider what the target platforms are, will be, and could be.
- Implementing in Java (for today's mass-market handsets) gives access to about 60 percent of the market, easily the largest target market.
- You need to make an educated guess about what new handsets will be arriving over the next year and allow for introduction of new technologies, such as hardware acceleration, which could completely change the look of the game.
- Handsets whose screen orientation can be changed on the fly are increasingly common, presenting some unique opportunities - for example, a labyrinth-style game might switch between the normal first-person view and a map view when the screen is rotated.
- An important design consideration is the range of input capabilities across the target platforms, which varies hugely: Different keypad and control layouts; changing the screen orientations; diagonal motion and simultaneous button pushes may be possible on some platforms; keyless touch screens must also be considered.
- Solutions for managing differing input capabilities include: multiple difficulty levels, defaulting to an easier level where some inputs are not possible; putting the same feature on multiple buttons; creating user-customizable controls.
- Current Java networks support only around 300- to 500-KB downloads.
- Varying handset performance, will always mean that game designs need to be scalable for widespread handset coverage, even more so with the 3D accelerated devices that are in the market now and, undoubtedly, with even faster ones emerging over the next year.
- On non-accelerated handsets it is possible to counter lower frame rates by mixing 2D and 3D graphics calls, so that, for example, a 3D character could be drawn over a 2D bitmap background.
- On accelerated platforms it is usually efficient to keep screen updates all 3D-based to allow optimal code paths through the low-level renderer and hardware.
- It is generally the case that if you design your game assets with hardware acceleration in mind, they will also run well on software renderers; the converse is not true.
- If you decide to use bitmaps for fonts, then you need to ensure that the bitmaps' widths and heights are powers of two for straightforward use as textures on a hardware accelerator. They also need to make sure that the download has enough space for all the languages required.
- The biggest headaches with multiplayer gaming are still the bugbears of latency and device variability, so games requiring fast response, such as first-person shooters or racing games, are still limited to high-end 3G handsets.
- Create assets at the highest possible quality - it is far easier to reduce the quality of the assets than increase it when tailoring for a particular handset and download size.
- In the mobile world a game has to be well behaved when a call or text message arrives. It must not cause problems with the normal use of the phone or interfere with other background applications.
- An incoming call on most platforms will cause a pause event to be sent to the game, which must suspend game time, stop updating the game world, and stop rendering. The game must also release any shared resource such as the 3D graphics rendering context in M3G. On more restricted platforms, the application may need to reduce memory use by deleting some of its assets.
- It's important for performance reasons not to allocate any memory at all in the main game loop.
- It's important to manage overall memory use, especially when using bitmaps or sounds. Loading resources when needed and then deleting them is critical, and this must be done so as not to cause fragmentation of the Java heap. Often the best solution is for game developers to write their own memory manager code so that the allocation and freeing of all resources is tightly controlled.
Google Collections (Page last updated April 2008, Added 2008-05-28, Author Dan Lewis, Publisher OCI). Tips:
- The most significant Google extensions of the Java Collections Framework are the new collections interfaces and their supporting implementations: BiMap, MultiMap, and MultiSet. They reside within the com.google.common.collect package.
- A bimap (or "bidirectional map") is a map that preserves the uniqueness of its values as well as that of its keys. This constraint enables bimaps to support an "inverse view", which is another bimap containing the same entries as this bimap but with reversed keys and values.
- A multimap is a map that may contain multiple values for the same key. There are three subinterfaces of Multimap: SetMultimap, ListMultimap, and SortedSetMultimap. SetMultimap ensures unique key/value pairs, while ListMultimap does not. ListMultimap, however, maintains the addition order of multiple values, and allows duplicates. SortedSetMultimap is like SetMultimap, but the multiple values for a given key are sorted by natural ordering.
- A Multiset, also referred to as a bag, preserves equality even when order is different like a set. Unlike a set, however, a bag may contain duplicates. Google Collections' Multiset provides a count method for counting duplicate members.
- The Lists.transform applies a function to every item in a given list. The function is not called until an element is accessed. This is important because changes in the given list after the transform will be applied.
Crunching Big Data with Java (Page last updated March 2008, Added 2008-05-28, Author Jim Falgout, Publisher JavaDevelopersJournal). Tips:
- To process large volumes of data efficiently, consider the way the data needs to flow to be transformed, processed, mined, cleansed, or matched to reach the end goal. Once you can break a data-intensive, analytic problem into such a form, it can be mapped to a dataflow graph that can be easily implemented.
- A dataflow implements pipeline parallelism by its very nature. Each process in a dataflow graph works independently (somewhat) of other processes in the graph. As a process handles its input and does its transformations, it writes the resulting data to its output. Pipelining is a very powerful construct that allows for simple parallelism.
- A data-oriented framework must be data scalable - it should be able to handle gigabytes to terabytes of data without relying on in-memory algorithms that fail when billions of rows of data have to be handled.
- On computers with multi-core hardware, divide and conquer (a k a horizontal partitioning) can provide a huge boost to performance.
- For larger datasets omparing every record to every other record is normally impossible (or at least would take an enormous amount of time). A technique to handle this is "blocking" - putting similar records into blocks of records for pairwise comparisons.
- To classify pairs of records, comparison methods used include: Levenshtein Edit Distance, Damerau-Levenshtein, Jaro, Jaro-Winkler, Q-Gram, and exact match. Each pair of fields is compared and generates a field score. Field scores are then used to classify the pair as either being a good match, a possible match, or not a match, for further processing.
- [Article includes a description of the performance tuning procedure followed to optimise performance for a specific implementation of massive data processing]
Fast String Search on Multicore Processors (Page last updated March 2008, Added 2008-05-28, Author Daniele Paolo Scarpazza, Oreste Villa, and Fabrizio Petrini, Publisher DrDobbsJournal). Tips:
- To reach top performance on multi-core systems you probably need to change your normal algorithms significantly. To exploit the memory subsystem at its best, a pipelined parallelization strategy, and data layout shuffling to fight congestion may be needed.
- The Aho-Corasick string search algorithm, which is famous for appearing in the original "fgrep" UNIX utility, is simple and can be expressed well as a branchless data flow. A variant of Aho-Corasick is based on a Deterministic Finite Automaton (DFA), and is fast for two reasons: it's based on a keyword tree (a trie); and no special rollback actions are required in case of mismatches.
Back to newsletter 090 contents
Last Updated: 2020-09-28
Copyright © 2000-2020 Fasterj.com. All Rights Reserved.
All trademarks and registered trademarks appearing on JavaPerformanceTuning.com are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. JavaPerformanceTuning.com is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
RSS Feed: http://www.JavaPerformanceTuning.com/newsletters.rss
Trouble with this page? Please contact us