DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 967,911 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for Java Performance - 1 - Introduction
Yousef Zook
Yousef Zook

Posted on • Updated on

Java Performance - 1 - Introduction

Recap

In the previous article, we demonstrated that we are going to discuss the great book Java Performance 2nd Edition by Scott Oaks.
In this article we are goind to summarize the first book chapter, Chapter 1: Introduction.
Please note that many senteces have been quoted from the book itself.
While you are reading this article, please consider that you are reading a summarized version of the chapter and chapter bold points only are included.

Great, let's start the first chapter...
Intro

Chapter Title:

Introduction

For who?

This book is designed for performance engineers and developers who are looking to understand how various aspects of the JVM and the Java APIs impact performance.
If it is late Sunday night, your site is going live Monday morning, and you’re looking for a quick fix for performance issues, this is not the book for you.

This is a book about the art and science of Java performance.

Java Platforms

The book has covered the performance of Oracle Hotspot JVM and Java Developement Kit JDK version 8 and 11, This is also known as Java, Standard Edition (SE).
These versions of the JDK were selected because they carry long-term support (LTS) from Oracle.

JVM tuning flags

JVM flags are curical parameters that you can pass to the java virtual machine to enhance the performance of your application.
With a few exceptions, the JVM accepts two kinds of flags: boolean flags, and flags that require a parameter.

  • Boolean flags use this syntax: -XX:+FlagName enables the flag, and -XX:-FlagName disables the flag.
  • Paramterized Flags that require a parameter use this syntax: -XX:FlagName=something, meaning to set the value of FlagName to something.

Tuning Flags
from jrebel.com

Hardware Platforms

From a performance perspective, the important thing about a machine is its number of cores. Let’s take a basic four-core machine: each core can (for the most part) pro‐ cess independently of the others, so a machine with four cores can achieve four times the throughput of a machine with a single core. (This depends on other factors about the software, of course.)
However adding more threads to this machine not necessirly increase throuput or make the program finishes quicker, will see more examples in the following chapters.

Software Containers

The biggest change in Java deployments in recent years is that they are now fre‐ quently deployed within a software container. That change is not limited to Java, of course; it’s an industry trend hastened by the move to cloud computing.
Two containers are important here:

  • Virtual Machine: which sets up a com‐ pletely isolated copy of the operating system on a subset of the hardware on which the virtual machine is running. From Java’s perspective (and the perspective of other applications), that virtual machine is indistinguishable from a regular machine with x cores and n GB of memory.
  • Docker Containers: A Java process running inside a Docker container doesn’t necessarily know it is in such a container. The Docker container is just a process (potentially with resource constraints) within a running OS, the way Java handles that differs between early versions of Java 8 (up until update 192) and later version of Java 8 (and all versions of Java 11).

The Complete Performance Story

This book is focused on how to best use the JVM and Java platform APIs so that programs run faster, but many outside influences affect performance.
Here are some notes for these outsides...

1.Write Better Algorithms:

Ultimately, the performance of an application is based on how well it is written. If the program loops through all elements in an array, the JVM will optimize the way it per‐ forms bounds checking of the array so that the loop runs faster, and it may unroll the loop operations to provide an additional speedup. But if the purpose of the loop is to find a specific item, no optimization in the world is going to make the array-based code as fast as a different version that uses a hash map.

2.Write Less Code

A small well-written program will run faster than a large well-written program.

So even if your code should be neat, extensible and easy to read, you should also consider the performance while writing your code.
A subset of the team may argue that they are adding a small piece of code which will not affect the perfromance, then another part calims the same, and after some repition you will find that the progress may be affected by 10%.
Over time, as the small regressions creep in, it will be harder and harder to fix them.

3.Oh, Go Ahead, Prematurely Optimize

premature optimization: A term often used by developers to claim that the performance of their code doesn’t matter, and if it does matter, we won’t know that until the code is run.
Notes:

  • If you are going to change the code to get better performance but this will lead to complicating the code and make it hard to fix in the future, then it's better to not do this enhancement till the profiling is done and points that this enhancement is mandatory.
  • However, if you have 2 choices and they are both straighforward and easy to make, and 1 of them will enhance the performance, then do it. Let's take the following example:
log.log(Level.FINE, "I am here, and the value of X is "
            + calcX() + " and Y is " + calcY());
Enter fullscreen mode Exit fullscreen mode

This code do string concatination and calls some functions calcX() and calcY(), when the log level is FINE. However this level of logging often are not used and it will not be printed, in this case it is better to check if it is loggable first to save the time of string concatination and the functions calls:

if (log.isLoggable(Level.FINE)) { 
    log.log(Level.FINE,
            "I am here, and the value of X is {} and Y is {}", 
            new Object[]{calcX(), calcY()});
}
Enter fullscreen mode Exit fullscreen mode

This avoids the string concatenation altogether (the message format isn’t necessarily more efficient, but it is cleaner), and there are no method calls or allocation of the object array unless logging has been enabled

4.Look Elsewhere: The Database Is Always the Bottleneck

If you are developing standalone Java applications that use no external resources, the performance of that application is (mostly) all that matters. Once an external resource (a database, for example) is added, the performance of both programs is important. And in a distributed environmentβ€”say with a Java REST server, a load balancer, a database, and a backend enterprise information systemβ€”the performance of the Java server may be the least of the performance issues.
If the database is the bottleneck, tuning the Java application accessing the database won’t help overall performance at all. In fact, it might be counterproductive. As a general rule, when load is increased into a system that is overburdened, performance of that system gets worse.

5.Optimize for the Common Case

we should focus on the common use case scenarios. This principle manifests itself in several ways:

  • Optimize code by profiling it and focusing on the operations in the profile taking the most time.
  • Apply Occam’s razor to diagnosing performance problems. The simplest explana‐ tion for a performance issue is the most conceivable cause: a performance bug in new code is more likely than a configuration issue on a machine, which in turn is more likely than a bug in the JVM or operating system.
  • Write simple algorithms for the most common operations in an application

πŸƒ See you in chapter 2 ...


πŸ’take a tip

Pareto principle: 80% of consequences come from 20% of causes.

Rule

Top comments (0)

🌚 Life is too short to browse without dark mode