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 January 2015
Get rid of your performance problems and memory leaks!
Get rid of your performance problems and memory leaks!
Back to newsletter 170 contents
ExecutorService - 10 tips and tricks (Page last updated November 2014, Added 2015-01-28, Author Tomasz Nurkiewicz, Publisher Nurkiewicz). Tips:
- Guava has helper classes to build ExecutorServices with nicer names, e.g.
Executors.newFixedThreadPool(10, new ThreadFactoryBuilder().setNameFormat("Orders-%d").setDaemon(true).build()); (by default thread pools create non-daemon threads, this example makes them daemons).
- You can change the current thread name with Thread.currentThread().setName().
- ExecutorService.shutdown() stops the pool from accepting further tasks but completes accepted tasks (including those queued); ExecutorService.shutdownNow() discards queued tasks.
- Create a pool with a fixed queue size with eg
new ThreadPoolExecutor(n, n, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100));.
- ExecutorService threads will swallow any exception - to log the exception surround your Runnable code with a try-catch.
- Time how long tasks wait to be processed so you know if there is an issue.
- Use CompletableFuture instead of Future, it's much more feature rich, allowing you to coordinate across multiple threads.
- An ExecutorService backed with SynchronousQueue will only accept tasks if there is a free thread (ie it won't queue tasks).
The Fatal Flaw of Finalizers and Phantoms (Page last updated December 2014, Added 2015-01-28, Author Jason Greene, Publisher InfoQ). Tips:
- The finalize() method is run before the object is ultimately discarded by the garbage collector, though there is no guarantee it will ever be run. It affects garbage collection efficiency. PhantomReference is often cited as a good alternative to finalizers.
- If finalizers are poorly written, that introduces the potential to delay other finalizers from executing, since they all tend to share the same execution thread pool.
- A class must never be designed to require that an action be taken by a finalizer, as they may never run.
- Garbage collection of an object with a finalize() method (not inherited from Object) is significantly more expensive than for those without.
- Uncaught exceptions in finalizers are never reported.
- Badly implemented finalizers can suffer from race conditions and can unintentionally resurrect objects in corrupt states.
- Objects can be collected earlier than you might expect (compiler optimization allows the object to be collectable even before it leaves it's scope if it is no longer used in that scope). This means that the finalize() method can run earlier than you might expect - including when calls to other object methods are concurrently running!
- If the finalizer is synchronized, it will not be invoked until after all other pending synchronized method calls have completed. But this approach can easily make a performance bottleneck.
- You can use a volatile field to signal to a finalizer when it is safe to execute.
- An AtomicIntegerFieldUpdater allows a class to perform a lazy write on volatile int fields. A lazy write is cheaper than a normal volatile write. A single AtomicIntegerFieldUpdater can lazily write the volatile fields of multiple objects.
Flavors of Concurrency in Java: Threads, Executors, ForkJoin and Actors (Page last updated December 2014, Added 2015-01-28, Author Oleg Shelajev, Publisher ZeroTurnaround). Tips:
- Java threads are mapped 1-1 to the operating system threads; the lifecycle of a thread is taken care of by the JVM and scheduling is not in your control.
- There's no good API to stop a Thread, your run() method needs to know this (eg with a volatile boolean if you need to signal stop from another thread).
- AtomicReference.compareAndSet(null, something) doesn't require locking and will ensure that only the first update will succeed.
- Using threads directly (rather than in a pool) is straightforward: multiple threads run and communicate via shared memory. The disadvantage is that it's easy to create too many threads.
- Too few threads will sacrifice potential parallelism; too many can lead to memory issues and scheduling conflicts.
- Executors class provides methods to create various types of thread pools and executors which give you access to operations occuring on each thread.
- Executors and associated thread pools is the right way to have precise control over how many threads your program generates and their exact behavior.
- The number of threads used by parallel streams is not defined by the application and uses a common pool for all stream operations globally (by default).
- Actor models emphasize avoiding global state, which comes with several benefits: retry for free, much simpler distributed system design, fault tolerance and more. This also means, though, that is can be difficult to integrate an actor based design with a traditional OO design.
Java Performance Tuning - A top down approach (Page last updated November 2014, Added 2015-01-28, Author Shivaji Chelladurai, Publisher DZone). Tips:
- Monitor the main system resources: Memory, CPU, IO Devices, Network IO. On Windows, use the Resource Monitor; on Unix use sar, top, dstat [not mentioned here but I like glances - Jack].
- Use JConsole to monitor the: command line args; heap usage (looking for leaks); dynamic class creation; application CPU usage.
- When there is a large difference in retained memory between a parent and child object, this is a good candidate for the holder of a memory leak
- Useful heap analysis tools include VisualVM, Java Mission Control, IBM Health Center and most commercial profilers for online analysis; and IBM Heap Analyzer and Eclipse MAT for analysing heap dumps (offline).
- Thread dumps provide thread status, monitors, number of threads waiting for the monitor and call stacks of methods - this is a useful record current and later analysis. Comparing thread dumps taken at different times can reveal execution hot spots.
- Useful execution profiling tools include VisualVM, Java Mission Control, IBM Health Center and most commercial profilers for online analysis; and IBM Thread and Monitor Dump Analyzer (offline).
- Identify the IO device that is most heavily utilized or not responding; and monitor network connections and bytes transferred.
- Simple IO anti-patterns include streams without buffering, repeated reads of the same resources, unnecessary serialization, non-reuse of connections, uncompressed transfers, failure to close resources (eg JDBC statements).
Supercharged jstack: How to Debug Your Servers at 100mph (Page last updated October 2014, Added 2015-01-28, Author Tal Weiss, Publisher takipi blog). Tips:
- jstack can easily show you the stack traces of all Java threads running within a target JVM. jstack is lightweight - it doesn't add any performance overhead to the JVM or change its execution state.
- If you set the thread name, it shows in jstack traces, so this is an excellent way of showing state for traces. So for longer requests, set the most useful request data in the thread name and this will show in the context of the stack trace for that thread. Alternatively, output variable data into the log with the thread id attached, so you can correlate the data with the stack trace.
- jstack has more powerful capabilities for showing you native frames and lock state than any calls from within the JVM.
Interrupting Executor Tasks (Page last updated November 2014, Added 2015-01-28, Author Bozhidar Bozhanov, Publisher bozho). Tips:
- Calling ExecutorService.shutdownNow() or Future.cancel() doesn't stop the ongoing runnable, these methods simply call interrupt() on the threads. You need to handle InterruptedException.
- If you have a loop in your Future task, you should test Thread.currentThread().isInterrupted() and terminate if that's true, closing any open resources.
- Cancelling running tasks asynchronously is hard - you need to think about how that can happen if your task is in a non-interruptible call like to a resource (often that requires another thread closing that resource so that the task can exit the call and terminate).
Back to newsletter 170 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