Cost of flow using exception - java

Imagine a simple banking application wherein a use case of fund transfer is being realized. While writing transfer fund operation, the programmer/designer has following two options
Write an operation to check if there are sufficient funds or not and return a Boolean based on which the subsequent fund transfer option will be carried out. This require creating two function viz. the checkSufficientFunds() and transferFund()
Write a single operation which itself checks if the funds are sufficient or not. This will throw an checked Exception if there are no sufficient funds and calling method have to handle this.
I understand that this is an oversimplified scenario. My question is, in theory, what are the performance implications (Memory and CPU) of these two approaches? How do they compare?

The performance difference in the current JVMs should be negligible. However, stick to the rule that exceptions should be used in exceptional situations. It is a normal flow not to have sufficient funds, so I would use a method public boolean transferFund() that returns true if successful, and false otherwise. This suggestion violates the command/query separation, but I think it's fine.

At runtime, try-catch blocks doesn't significantly affect performance. Only when an exception occurs and in theses cases you must handle the exception anyway. But you have to use exceptions only when they are required (when the app is unable to preceeed normally).

This assignment is more about atomic operations. In the first scenario it is possible to overdraft an account whereas in the second you roll everything back (or should).
In terms of performance any time you generate a stack trace that consumes memory and time. Iirc it makes an execution path 70x more expensive.

If I was doing a code-review and someone motivated the choice between using exceptions vs method calls by performance considerations, I would down-mark that developer. It's a text-book case of sub-optimization and a waste of time. Optimize where it matters and has a measurable impact. Don't shave milliseconds at the cost of code quality and robustness.
As for this case - some people like to use exceptions as a flow-control mechanism. I don't. Exceptions, in my view, are used to indicate reaching an unexpected state. Often, this is analogous to an error. Checked exceptions imply that the state is something that could conceivably be recovered from within the scope of the current transaction or conversition. An unchecked exception implies that there is no reliable recovery and the system should alert the user.

The performance impact is unlikely to get great enough to worry about. However, I would still recommended using Exception for exceptional situations. In this case you don't need two methods. You can have
boolean transferred = transferFundsIfAvailable( ... );
A reason using two methods is undesirable is that it could cause race conditions, even if the individual methods are thread safe. Say you have
if(checkSufficientFunds()) {
// another thread transfers funds
transferFund(); // but there is not enough any more
}
Also you could forget to call the check first. You are better off without it.

Related

Java, does overusing try/catch result in performance issues?

i thought about the fact, that using try and catch is useful to prevent crashes if there are mistakes, but i was curious if there is any impact at the performance if i overuse the try and catch block.
To resume: Is there any impact at the performance if i use try and catch(nearly) everywhere?
Exception throwing/handling does come with a slight performance penalty (the exact amount varies greatly by the exact scenario), but performance shouldn't be your first consideration.
Correctness: First of all, make sure that your code does what it needs to do. Don't treat normal use cases as exceptional, for example if a user types in an incorrect value in a field, that's nothing special, no need to throw exceptions for that. But if something is genuinely exceptional (like you can't connect to the database), and you can't deal with it at the point it occurs, throw an exception. And if the exception comes from "below", from a JDK class or a third party library, you have no other option than to handle it.
Readability. Constantly catching and re-throwing exceptions can make your code near impossible to follow, debug or maintain. The same goes for swallowing exceptions without a trace. What you should aim for instead is a consistent strategy for handling exceptions. Basically you should only handle exceptions on the level where you can do something about them.
Performance. This should be your last port of call, once you get the first two sorted. It is unlikely that you'll ever be in a place where your code is correct and readable, and still exception handling is the main bottleneck of your application, but if you do get there, you can try returning error codes rather than throwing exceptions, or completely restructuring your code to avoid them.
I think the main hit to performance you are going to see (assuming the code in question is executed at a very high frequency) will be from garbage collection.
One trivial example (this you do actually see in production code every now and then ...) would be having password verification logic like:
if (!password.equals(correctPassword)) {
throw new IncorrectPasswordException();
}
and then ...
catch (final IncorrectPasswordException ex) {
//some output or so
}
... instead of simply never throwing anything and just handling this via conditionals. You will eventually have to clean up all those IncorrectPasswordException from memory.
In this case overusing exceptions actually will become pretty costly by turning simple evaluations into object instantiations that cost you memory and even more importantly eventually cost you precious CPU cycles for reclaiming that memory via garbage collection.

Mutate Non thread safe collections

Can anyone please explain to me the consequences of mutating a collection in java that is not thread-safe and is being used by multiple threads?
The results are undefined and somewhat random.
With JDK collections that are designed to fail fast, you might receive a ConcurrentModificationException. This is really the only consequence that is specific to thread safety with collections, as opposed to any other class.
Problems that occur generally with thread-unsafe classes may occur:
The internal state of the collection might be corrupted.
The mutation may appear to be successful, but the changes may not, in fact, be visible to other threads at any given time. They might be invisible at first and become visible later.
The changes might actually be successful under light load, but fail randomly under heavy load with lots of threads in contention.
Race conditions might occur, as was mentioned in a comment above.
There are lots of other possibilities, none of them pleasant. Worst of all, these things tend to most commonly reveal themselves in production, when the system is stressed.
In short, you probably don't want to do that.
The most common outcome is it looks like it works, but doesn't work all the time.
This can mean you have a problem which
works on one machine but doesn't on another.
works for a while but something apparently unrelated changes and your program breaks.
whenever you have a bug you don't know if it's a multi-threading issue or not if you are not using thread safe data structures.
What can happen is;
you rarely/randomly get an error and strange behaviour
your code goes into an infinite loop and stops working (HashMap used to do this)
The only option is to;
limit the amount of state which is shared between threads, ideally none at all.
be very careful about how data is updated.
don't rely on unit tests, you have to understand what the code doing and be confident it will be behave correctly in all possible situations.
The invariants of the data structure will not be guaranteed.
For example:
If thread 2 does a read whilst thread 1 is adding to the DS thread 1 may consider this element added while thread 2 doesn't see that the element has been added yet.
There are plenty of data structures that aren't thread-safe that will still appear to function(i.e. not throw) in a multi threaded environment and they might even perform correctly under certain circumstances(like if you aren't doing any writes to the data structure).
To fully understand this topic exploring the different classes of bugs that occur in concurrent systems is recommended: this short document seems like a good start.
http://pages.cs.wisc.edu/~remzi/OSTEP/threads-bugs.pdf

How Often Will Java Sync To Main Memory?

I have a set of counters which will only ever be updated in a single thread.
If I read these values from another thread and I don't user volatile/atomic/synchronized how out of date can these values be?
I ask as I am wondering if I can avoid using volatile/atomic/synchronized here.
I currently believe that I can't make any assumptions about time to update (so I am forced to use at least volatile). Just want to make sure I am not missing something here.
I ask as I am wondering if I can avoid using volatile/atomic/synchronized here.
In practice, the CPU cache is probably going to be synchronized to main memory anyway on a regular basis (how often depends on many parameters), so it sounds like you would be able to see some new values from time to time.
But that is missing the point: the actual problem is that if you don't use a proper synchronization pattern, the compiler is free to "optimise" your code and remove the update part.
For example:
class Broken {
boolean stop = false;
void broken() throws Exception {
while (!stop) {
Thread.sleep(100);
}
}
}
The compiler is authorised to rewrite that code as:
void broken() throws Exception {
while (true) {
Thread.sleep(100);
}
}
because there is no obligation to check if the non-volatile stop might change while you are executing the broken method. Mark the stop variable as volatile and that optimisation is not allowed any more.
Bottom line: if you need to share state you need synchronization.
How stale a value can get is left entirely to the discretion of the implementation -- the spec doesn't provide any guarantees. You will be writing code that depends on the implementation details of a particular JVM and which can be broken by changes to memory models or to how the JIT reorders code. The spec seems to be written with the intent of giving the implementers as much rope as they want, as long as they observe the constraints imposed by volatile, final, synchronized, etc.
It looks like the only way that I can avoid the synchronization of these variables is to do the following (similar to what Zan Lynx suggested in the comments):
Figure out the maximum age I am prepared to accept. I will make this
the "update interval".
Each "update interval" copy the unsynchronized counter variables to synchronized variables. This neeeds to be done on the write thread.
Read thread(s) can only read from these synchronized variables.
Of course, this optimization may only be a marginal improvement and would probably not be worth it considering the extra complexity it would create.
Java8 has a new class called LongAdder which helps with the problem of using volatile on a field. But until then...
If you do not use volatile on your counter then the results are unpredictable. If you do use volatile then there are performance problems since each write must guarantee cache/memory coherency. This is a huge performance problem when there are many threads writing frequently.
For statistics and counters that are not critical to the application, I give users the option of volatile/atomic or none with none the default. So far, most use none.

Is there a way to tell from within the JVM whether a particular method has been JIT compiled?

When writing microbenchmarks, one can observe a large difference in runtime depending on whether a method has been compiled or not. Is there a way to tell from within a program whether a particular method has been compiled? Alternatively, is there a way to request it, or to know how to warm it up adequately without any extra information about e.g. flags passed to the JVM? Obviously this will not necessarily be perfect (e.g. there may be some condition present that causes the JVM to fall back to interpreted code), but it would certainly be an improvement.
For Sun/Oracle JVM you can use the -XX:CompileThreshold=1000 setting.
This - as the official documentation states - defines:
Number of method invocations/branches before compiling
Then, just use the number to "warm up" the JVM.
You can also use the -XX:-PrintCompilation together with -XX:CompileThreshold in order to be notified (in the console) when a method is compiled.
I'm pretty sure you can turn on logging that will show when methods are JITCed. But I don't know of any way from within Java to tell.
And keep in mind that JIT compilation is not an event but a process -- a method may be recompiled several times, as more information about its characteristics becomes available.
Finally, note that "warming up" is iffy in the general case. While you can usually "warm up" a single method reliably, it's much harder with even a modestly large application, due to a number of factors.
(Though I don't know of any reason why the ability to read some sort of JITC status for a method could not be added to embedded debug tools.)
Added: One thing to beware of, when benchmarking code "snippets", is that the outer-most method that does all the looping is often not JITC-able (depending on how the JITC is implemented) due to the fact that it never returns and hence the JITCed version can never be called. So one should always place the "meat" of the code to be benchmarked in a separate method that is called repeatedly, vs putting the loop and the to-be-benchmarked code in the same method.

Java byecode maniulation to detect potential deadlocks

I've been caught by yet another deadlock in our Java application and started thinking about how to detect potential deadlocks in the future. I had an idea of how to do this, but it seems almost too simple.
I'd like to hear people's views on it.
I plan to run our application for several hours in our test environment, using a typical data set.
I think it would be possible to perform bytecode manipulation on our application such that, whenever it takes a lock (e.g. entering a synchronized block), details of the lock are added to a ThreadLocal list.
I could write an algorithm that, at some later point, compares the lists for all threads and checks if any contain the same pair of locks in opposite order - this would be reported as a deadlock possibility. Again, I would use bytecode manipulation to add this periodic check to my application.
So my question is this: is this idea (a) original and (b) viable?
This is something that we talked about when I took a course in concurrency. I'm not sure if your implementation is original, but the concept of analysis to determine potential deadlock is not unique. There are dynamic analysis tools for Java, such as JCarder. There is also research into some analysis that can be done statically.
Admittedly, it's been a couple of years since I've looked around. I don't think JCarder was the specific tool we talked about (at least, the name doesn't sound familiar, but I couldn't find anything else). But the point is that analysis to detect deadlock isn't an original concept, and I'd start by looking at research that has produced usable tools as a starting point - I would suspect that the algorithms, if not the implementation, are generally available.
I have done something similar to this with Lock by supplying my own implementation.
These days I use the actor model, so there is little need to lock the data (as I have almost no shared mutable data)
In case you didn't know, you can use the Java MX bean to detect deadlocked threads programmatically. This doesn't help you in testing but it will help you at least better detect and recover in production.
ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
long[] deadLockedThreadIds = threadMxBean.findMonitorDeadlockedThreads();
// log the condition or even interrupt threads if necessary
...
That way you can find some deadlocks, but never prove their absence. I'd better develop static checking tool, a kind of bytecode analizer, feeded with annotations for each synchronized method. Annotations should show the place of the annotated method in the resource graph. The task is then to find loops in the graph. Each loop means deadlock.

Categories