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 April 2007
Get rid of your performance problems and memory leaks!
Get rid of your performance problems and memory leaks!
Back to newsletter 077 contents
Interviewing Ron Bodkin (Page last updated April 2007, Added 2007-04-30, Author Kirk Pepperdine, Publisher fasterj.com). Tips:
- Glassbox is an open source Java monitoring solution that installs very quickly. It is also a great foundation for building application-specific monitoring.
- It is important to automate and simplify the common problems, to minimize downtime and expenses.
- Writing distributed calls like they are local is a big problem: it's a problem in database interaction, in Web services calls, and in chatty AJAX applications.
- Many projects would benefit by creating prototypes of their high risk components, and load test them early on to verify performance and reliability assumptions
Java grid computing (Page last updated March 2007, Added 2007-04-30, Author Corey Klaasmeyer, Publisher JavaWorld). Tips:
- A computational grid is a hardware and software infrastructure that provides dependable, consistent, pervasive and inexpensive access to high-end computational capabilities.
- Grids solve the complicated problem of providing computing resources to groups that span organizational boundaries.
- Clusters pay the price for lower cost hardware in communication overhead and RAM size.
- Clusters can prove invaluable in high-performance computing for solving problems that can easily be broken into many smaller tasks and distributed to workers.
- Clustered problems ideally require little communication between workers, and their work product can be combined or processed in some way after the tasks have been completed.
- Some algorithms lend themselves to grid style parallelization, for instance it's easier to make algorithms parallel if the results from one piece of work do not have to be fed into another piece of work.
- [Article runs through an example of creating a grid service to search for Mersenne primes]
Preventing Screen Lockups of Blocking Operations in MIDlets (Page last updated March 2004, Added 2007-04-30, Author Qusay H. Mahmoud, Publisher Sun). Tips:
- When you're developing networking MIDlets, pay special attention to blocking operations, such as methods that establish a connection to the network. These can lock up the screen, leaving your user frustrated with your application.
- To prevent screen lockups, you should perform all blocking operations in a separate thread.
- Have the MIDlet implement the Runnable interface and any user click that would initiate a blocking operation should starts a new thread whose run() method calls the method that would otherwise be invoked by the click.
- [Article includes a worked example of processing a blocking MIDlet call in the background to avoid blocking the UI].
A performance-based approach to sizing infrastructure (Page last updated April 2007, Added 2007-04-30, Author George Dolbier, Publisher IBM). Tips:
- An optimized grid based application allows the infrastructure to expand and contract without disruption to user activity.
- Only network throughput and latency requirements on the client have any impact on the server infrastructure: understand these issues first when trying to figure out the size of the physical infrastructure required
- Multiplayer online games aim to do better than 60 frames a second.
- Homogeneous-type architectures have multiple equal servers that are not stratified - in many cases servers and don't even have to communicate with each other. In slightly more sophisticated cases servers communicate with each other as equals to support the overall system - in this architecture, each server contributes equally. When the load grows, more servers are simply added to the mix. If implemented properly, the system will begin to utilize the new servers automatically.
- Tiered- or shard-type architectureS has a layer of servers. Each tier communicates with another layer of servers that performs a specific function. When capacity needs to be expanded, servers are added to each layer.
- The term "shard" is commonly used to describe individual servers that are designed around a traditional multitiered Model-View-Controller (MVC) application pattern.
- A shard is divided into three primary layers: database layer; application servers; front end (login, border, boundary, and load balancing). That is topped off with a firewall.
- Global sizing starts with determining the global target userbase; next, break that down to userbase per geography; then break that into sites per geography. Factor by the number of users who can be supported by each instance of the system, and you have the basic infrastructure size.
- A front tier has to be a combination of high-performance network hardware and good security features, along with a layer of firewalls with a proven track record of defending against denial-of-service, packet fragment, and other typical brute-force attacks on Internet sites.
- Sizing of the middle tiers depends on the architecture of the system. (600 concurrent users per server seems to be the current peak support levels for real-time multiplayer games).
- To minimize database latencies, data schemas in real-time multiplayer games are deliberately kept simple, and the transactions executed on these tables are all simple updates and reads.
- Sizing is essentially achieved by finding the single largest bottleneck, then sizing is based on a performance pay-off of resources to ameliorate that bottleneck. (In real-time multiplayer games the main bottleneck is almost always the network).
- Resources are easy to justify when a key bottleneck is found and performance can be improved by a large factor.
- Sizing the middle tier is usually based on CPU and memory limitations - determine the number of concurrent users and the amount each takes, and that usually identifies the CPU and memory required.
- Sizing the database layer is relatively easy. The answer is two - for an active-active fault tolerant cluster.
- For a client server system aiming for high frequency updates, the latency is determined by core decisions about the processing engine and the communication protocol.
- Well-understood techniques to minimize communications overheads are: caching, perfecting data, queue optimization, out-of-order transmission and receipt, connection pooling, hints, and parallel connections.
- For WAN links, the speed and latency to the Internet is critical: select multiple hosting facilities throughout the market and ensure that those hosting facilities have low-latency connections with the broadband providers that serve the particular markets - ideally host within a broadband service provider's infrastructure.
The Right Stuff (Page last updated April 2007, Added 2007-04-30, Author Rex Black & Barton Layne, Publisher Better Software Magazine). Tips:
- Static Performance Testing: A model of system behavior under various load levels, e.g. a spreadsheet estimating resource utilization level of CPU, memory, network bandwidth, etc. Should feed into the starting design.
- Static Performance Analysis: A simulation of the proposed system (possibly created using a static model design of the system) which enables you to test proposed loads.
- Unit Performance Testing: Each significant component of the system is load tested separately.
- System Performance Testing: Testing the whole system under loads expected to be representative or exceeding the expected loads by a known amount.
- Create real, user-like operations against the production infrastructure.
- Try to provide quick feedback about performance problems to the development team.
- System performance testing should also test forced system and component failures.
- A major challenge of performance testing is testing in a "production-like" environment rather than the actual one, which can lead to all sorts of issues undetected and some issues spuriously detected.
- Be careful to ensure that the tests are valid and properly executed.
- Excessively large log files often cause performance problems.
- Memory leaks frequently result in performance degradation.
Five Ajax anti-patterns (Page last updated March 2007, Added 2007-04-30, Author Jack D Herrington, Publisher IBM). Tips:
- Whenever you see window.setInterval() it should set off a little alarm in your mind; why is this timer being used? Timers have their purpose - animations, for example. But mostly they are unnecessary.
- One place a timer is certainly not necessary is to watch for an Ajax request to finish. Instead you should be using the onreadystatechange callback
- Don't make requests to the server over and over again if the request hasn't changed. Instead use the onkeyup() function.
- Instead of immediately running a request onkeyup(), set it to run in a second, and keep resetting it if the user is still typing - that way if the user is typing a lot of text, it only gets called when they have paused typing and not on every keystroke.
- Guard the inspection of callback return results with
req.readyState == 4 && req.status == 200 to avoid handling multiple intermediate (incomplete) callbacks.
- Determine whether to process in the server or client according to load and client responsiveness - some things will be better to process on the server, some on the client, and that decision is also likely to depend on overall load (too much on the server and everything slows down).
Controlling Threads by Example (Page last updated April 2007, Added 2007-04-30, Author Viraj Shetty, Publisher OnJava). Tips:
- Long running tasks executed on the GUI thread freezes the interface for user input and makes for a bad impression of performance.
- [Article provides a worked example of making a GUI performa long running tasks while keeping the UI response to user initiated activity].
- Long running tasks started from the GUI should be run in a separate thread so as not to block the UI.
- Updates to a Swing UI needs to be performed in the screen updating thread. In order to do this from other threads, use SwingUtilities.invokeLater to schedule updates onto the Swing updating thread.
- Thread.interrupt() is the standard mechanism for interrupting a thread from another thread. The target thread should be ready to handle an interrupt by regularly checking Thread.currentThread().isInterrupted(), and then acting on the interrupt.
Back to newsletter 077 contents
Last Updated: 2018-09-22
Copyright © 2000-2018 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