How to Improve Performance of Java App?
Whether you are a project manager at cyber-security startup or a CTO at an established fintech company, you‘ll probably come across Java application development at some point. You may be an experienced developer or a CEO with no Java experience. Either way, your top priority is the best possible user experience. An optimized product is one of the best ways to improve security, speed, and overall performance of your application, platform, or however you might use Java.
Java can be a tricky language to learn, but over 10 million developers use it to build applications and solve real-world problems every day. From Fortune 500 companies to Android users, everyday life for billions of people involves Java in one way or another. It remains one of the most sought after development skills in the job market, and Oracle has big plans for Java application performance with JDK 10 and the upcoming Java 11 LTS.
Optimization is an endless quest for performance, and it‘s no easy task. Countless small improvements can add “money-for-nothing” to the overall performance, but it‘s up to you to find them. For Java developers and anyone working in Java, there are dozens (if not hundreds) of tweaks, tips, and tricks to improve Java performance. Some of the tips I collected related to application development in general, but most of them are specific to Java application performance tuning in particular. The list below offers simple strategies to improve Java application performance using some reliable old Java tricks along with some new ones.
One of the key things I‘ve learned about optimizing for peak java application performance is the fact that 90 percent of the problem is only 10 percent of the code. For most applications, there is a strong Pareto distribution of task resource consumption. “The 80/20 Rule” is a useful guide, but I figure it is closer to 90/10 or 95/5. A small portion of your overall application tasks will consume the lion‘s share of the resources for your web app or whatever you want to optimize.
Read on to learn more about performance tuning including tips about Java optimization.
Profiler vs. Bad Guesses
Debugging the Debugger
Stack vs. Heap
Start Small Heap
Sets Over Elements
My Final Thoughts
Java Application Performance Tuning Tips
Biggest Bottleneck First
Once you have a test suite and a profiler set up, you‘ll have a bunch of issues to review. My “95/5 Rule” applies here – start with the most pertinent problems and focus on significant performance issues. Think about the Big Picture here. It‘s easy to get bogged down when you are trying to improve Java application performance. Start at the front and work your way to the back. Most performance issues relate to one or two major issues. Bear in mind that the vast majority of your code won‘t significantly improve Java performance with optimization. Focus on the common tasks that occur frequently!
Performance Test Suite
Tweaking Java or anything else is all about small changes over time. Without good reference points, it‘s impossible to accurately compare A vs. B. A performance test suite is a great tool to test your Java application to give you the before-and-after along with side effects and functional problems down the road. The performance test suite is especially important when working on multi-functional components such as caches, databases, and the like. It‘s easy to do damage in the chase for better J2EE application performance optimization. Before you spend unnecessary hours in front of your monitor, make sure you use a performance test suite to help make good decisions.
Profiler vs. Bad Guesses
Once you decide that you want to attempt Java application performance tuning, the first move should be finding a profiler to use. When I first started to optimize Java application performance, I would look at my code and make a guess as to where the problems might be. I was usually wrong – my first guess often led me astray. Once I started to use a profiler, my life became a lot easier. Profilers can help you analyze your code to help you better understand the impact of changes and identify performance problems at the source. I‘m typically a bit surprised when I read the profiler reports, and it‘s easy to overlook performance issues without the detailed performance and behavior information from the profiler.
Recursion is Bad
Some modern functional languages want developers to use recursive code to help optimize tail-recursing into iterative code, but it‘s generally a bad practice. It‘s better not to rely on this method for Java application performance tuning. The problem arises when a slight change in the algorithm kills a tail-recursive branch. A good compiler ought to detect this kind of thing, but it‘s not a guarantee. The danger here is spending stack frames unnecessarily. Local variables can help avoid recursion problems, and it makes for better code as a general rule to improve Java performance.
Control Your Concurrency
Running several programs at the same time is often a performance drag. Concurrency across threads creates the opportunity for parallel processing, but it takes a keen understanding of Amdahl‘s law and the relational database management system to achieve the best Java application performance. For example, multi-request web flows are best served by optimistic-locking using detached entities. Using the data access framework properly will improve data-access layer performance, and this strategy can lead to optimization gains for the overall application.
BigInteger and BigDecimal – Just Say No
There is always a trade-off between precision and speed for any activity – just ask any anyone who plays “pinfinger.” Developing in Java is no different, and mathematical algorithms are a common source of performance drag. The right data type can make all the difference here. BigDecimal is very popular for its precision, but it requires a ton of memory when compared to something simple like double or long. I‘m not too proud to admit that this single optimization has solved my J2EE application performance problems more than once.
Debug your Debugger
A common error in Java is the unnecessary activation of the debug log. It‘s tempting to just drop in a log.debug where you need it, but don‘t forget to add if (log.isDebugEnabled()) or you will fire up a String for a debug message that your logging framework will ignore anyway. If you check first, you can save time here. Java application performance is all about little improvements and good programming practices. Doing it right the first time and developing good habits will save frustration and reworking in the future. Java application performance tuning is all about little wins here and there to keep your overhead down and performance humming along. Don‘t let your debugger hold back your application.
Hire expert developers for your next project
1,200 top developers
us over the last 3 years
Use the Stack and Avoid the Heap
It‘s not always possible, but it‘s a good idea to use primitive types in the stack as much as you can. For example, it‘s far better to use int over Integer wherever possible. Same goes for Double and double. Using stack storage instead of heap storage limits the use of memory consumption. It‘s just a good practice for efficient handling in your code, and it keeps your overhead down. Wrapper classes have their uses, but do your best to avoid them to keep your application lean and mean. Improving Java application performance is all about minimizing memory use wherever you can. Whenever possible, avoid using the heap when the stack will do. Primitive types are a great way to maintain this discipline and keep your overhead low.
Starting Small with the Heap
Memory is the currency of optimization. It‘s a valuable resource that you should treasure. I often think about it like money. Businesses need to run on the lowest cost base possible to maximize their profit off a given amount of revenue. Java application performance tuning is similar – lean and mean wins in the end. It‘s always a good idea to start with the minimum memory allocation. It‘s all about speed, so make sure you use as little memory as possible to keep your overhead down. Try to be like the Costco of Java development – fast, smart, and lean on cost. Use the minimum memory allocation for your heap, and work your way up as necessary.
The phrase “premature optimization” is something I try to keep in mind when developing in Java. It‘s tempting to try to improve Java performance as you go, optimizing on the fly to write the best possible code. The problem here is I don‘t know where the bottleneck will be until I‘m close to the finish line. Don‘t waste your time on process optimization early in the development cycle. It just makes your code harder to read, difficult to maintain, and overly complex. Focus on the function first, and then go back to optimize your Java application performance once you know where to devote your optimization efforts.
Think Sets, Not Individual Elements
Concise algorithms using sets is a great way to optimize Java application performance. “Sets over elements” thinking is a key skill with Java and most other programming languages. It‘s often tempting to go from problem-to-problem with simple and local algorithms in your code. Big Picture thinking is a better way to approach application development, and sets are a good thing to master in order to work this way. Sets can help you avoid low-level calls that you often find with individual elements in your code.
To Cache or Not to Cache
Repetitive executions can add up when it comes to expensive or common code. Reusing your resources is more efficient and cheaper than generating new ones again and again. Caching is a good way to improve responsiveness, and I use it to optimize my Java application performance whenever I can. Like many things, there is a balance between caching and overhead. Memory is a valuable resource, and it‘s not worth caching everything. Focus on resources in heavy use, and don‘t fall into the temptation to over-cache lesser resources. Just because you can doesn‘t mean you should! A good profiler and performance test suite can help you decide whether to cache certain resources or not.
The Final Word
Java application performance tuning is an important step in the development cycle for many of my projects. Getting the most out of your code is a rewarding process, and it feels good to find improvements that make a difference. There‘s always a trade-off between time and reward, so I always try to keep the Big Picture in mind. The “95/5 Rule” is an important metric that I always try to remember. Too many times, I have found myself caught in the optimization trap. If I‘m going to be spending my time staring at my monitor while doing Java application performance optimizations, I try to focus on where it counts. It doesn‘t take much to make a big difference if you improve in the right areas.
Writing the code perfectly the first time? It‘s just not possible. There is a natural balance between form and function when you develop in Java, and I find it‘s better to get the thing built first. Once I have a final product to improve, then I worry about performance optimization. Focusing on function first gives me space to be more creative and think about the problem as a whole. Optimization is there to help me improve my original ideas to make them lean, mean, and ready to work. Worried about your own Java applications? Need help with performance optimization and lean development? DevTeamSpace has a great team with lots of expertise and experience with Java development and Java application performance tuning. You can learn more about our projects and read other articles about software development here.