Call Method based on user preferences, which is faster/better - java

We have X methods and we like call the one relative to user settings which of the following runs faster?
Case 1:
int userSetting = 1;
Method method = Class.getDeclaredMethod("Method" + userSetting);
method.invoke();
Case 2:
int userSetting = 1;
switch(userSettings) {
case 0:
Method0();
break;
case 1:
Method1();
break;
...
...
}
Case 3:
int userSetting = 1;
if(userSetting == 0){
Method0();
} else if(userSetting == 1){
Method1();
} else....
Also:
You think one even if slower is better practice that the others? If yes why?
There is another way witch is better/faster...please tell us.
Thanks

Option 1 uses reflection, and thus will probably be slower, as the javadocs indicate:
Performance Overhead
Because reflection involves types that are dynamically resolved, certain Java
virtual machine optimizations can not be performed. Consequently, reflective
operations have slower performance than their non-reflective counterparts,
and should be avoided in sections of code which are called frequently in
performance-sensitive applications.
However it is easier to maintain this option then options 2+3.
I would suggest you to use a complete different option: use the strategy design pattern. It is more likely to be faster and much more readable then the alternatives.

As amit points out, this is a case for the Strategy design pattern. Additionally, I want to give a short example:
Pseudo-Code:
public interface Calculator {
public int calc(...);
}
public class FastCalc implements Calculator {
public int calc(...) {
// Do the fast stuff here
}
}
public class SlowCalc implements Calculator {
public int calc(...) {
// Do the slow stuff here
}
}
You main program then decides which strategy to use based on the user preferences:
Calculator calc = userPreference.getBoolean("fast") ? new FastCalc() : new SlowCalc();
int result = calc.calc(...);
This is because later, you can use the Factory pattern to create multiple strategies for various operations:
Factory factory = new SlowFactory();
Calculator calc = factory.createCalculator();
Operation op = factory.createSomeOtherOperation();
Factory factory = new FastFactory();
Calculator calc = factory.createCalculator();
Operation op = factory.createSomeOtherOperation();
As you can see, the code is the same for the Slow case and for the Fast case, except the factory class, and that you can create by deciding based on the user preference. Especially if you have more such operations, such as Calculator and my Operation example, then you will want your code to not be dependent on the user preference everywhere but only at a single place.

I think the obvious slowest version is number one. reflexion is complex and is done during the runtime. for number 2 and number 3 you could have a look at Java: case-statment or if-statement efficiency perspective.
another way: could the configuration of the user change during the execution? if not, make the decision only one time on start-up.

Case 1 uses reflection and suffers a performance hit beyond approaches 2 and 3.
Between approaches 2 & 3 performance difference would be marginal at most. You must ask yourselves if any possible performance gain is really justified over code readability? Unless being on a truly limited microchip or similar I would always answer no.
Apart from the performance view, as #HoeverCraft Full Of Eels already pointed out you're probably better of redesigning your program to completely avoid the series of conditional clauses.

As all others have said #1 will most likely be the slowest.
The differences between 2 and 3 are negligible, but generally #2 shouldn't be slower than #3, because the compiler can change a switch to a cascaded if, if it thinks it would be faster. Also since the switch is clearly better readable than the if/else cascade I'd go with the second anyhow.
Although I'm extremely sure that this isn't the bottleneck anyhow - even if using reflection..

Related

Does using a map truly reduce cyclomatic complexity?

Suppose I have the original method below.
public String someMethod(String str) {
String returnStr;
if("BLAH".equals(str)) {
returnStr="ok";
} else if ("BLING".equals(str)) {
returnStr="not ok";
} else if ("BONG".equals(str)) {
returnStr="ok";
}
return returnStr;
}
Does converting to below truly reduce CC?
Map<String, String> validator = new HashMap<String,String>();
validator.put("BLAH","ok");
validator.put("BLING","not ok");
validator.put("BONG","ok");
public String someMethod(String str) {
return validator.get(str);
}
Yes, in your case. In simple terms, cyclomatic complexity is a number of linear-independent ways to reach the end of code piece from starting point. So, any conditional operator increases CC of your code.
(if OP's question is somehow related to testing tag) However, reducing CC doesn't reduce count of unit test which have to be written to cover your code: CC gives you only a lower bound of test count. For good coverage unit tests should cover all specific cases, and in second case you don't reduce this number of specific cases, you only make your code more readable.
Yes, because the cyclomatic complexity defines the number of linear independent paths in the control flow graph plus one. In your second example, there is only one path, the first has multiple path through if branches. However, it does not seem that cyclomatic complexity is really a problem here. You could substitue your method like this, to make it better readable:
public String someMethod(String str) {
switch(str) {
case "BLAH":
case "BONG": return "ok";
case "BLING": return "not ok";
default: return null;
}
}
Short answer : yes, the usuage of Hashmap in your case does reduce Cyclomatic complexcity.
Detailed answer : Cyclomatic complexcity as per wikipedia is
It is a quantitative measure of the number of linearly independent paths through a program's source code.
There are various ways to tackle if-else cases. If-else statements makes the code less readable, difficult to understand. These if-else are also bad as each time you have addition / deletion / modification in the cases then you need to modify the existing code files where your other business logic remains same, and due to change in these files you need to test them all over again. This leads to maintainance issues as well as at all the places we need to make sure to handle the cases. Same issues exists with switch statements too, though they are little more readable.
The way you have used also reduces the different logical paths of execution.Another alternative approach is as below.
You can create an interface say IPair. Let this interface define an abstract method public String getValue(); Lets define different classes for each case we have and let BlahMatch.java, Bling.java and Bong.java implement IPair and in the implementation of getValue() method return the appropriate String.
public String someMethod(IPair pair) {
return pair.getValue();
}
The advantage of above approach is, in case you have some new pair later you can still create a new class and pass the object of your new class easily, just you need to have your class provide implementation for IPair.

HashMap vs Switch statement performance

A HashMap essentially has O(1) performance while a switch state can have either O(1) or O(log(n)) depending on if the compiler uses a tableswitch or lookup switch.
Understandably, if a switch statement is written as such,
switch (int) {
case 1:
case 2:
case 3:
case 4:
default:
}
then it would use a tableswitch and clearly have a performance advantage over a standard HashMap. But what if the switch statement is sparse? These would be two examples that I would be comparing:
HashMap<Integer, String> example = new HashMap<Integer, String>() {{
put(1, "a");
put(10, "b");
put(100, "c");
put(1000, "d");
}};
.
switch (int) {
case 1:
return "a";
case 10:
return "b";
case 100:
return "c";
case 1000:
return "d";
default:
return null;
}
What would provide more throughput, a lookupswitch or HashMap?
Does the overhead of the HashMap give the lookupswitch an advantage early but eventually tapers off as the number of cases/entries increase?
Edit: I tried some benchmarks using JMH, here are my results and code used. https://gist.github.com/mooman219/bebbdc047889c7cfe612
As you guys mentioned, the lookupswitch statement outperformed the HashTable. I'm still wondering why though.
The accepted answer is wrong here.
http://java-performance.info/string-switch-implementation/
Switches will always be as fast as if not faster than hash maps. Switch statements are transformed into direct lookup tables. In the case of Integer values (ints, enums, shorts, longs) it is a direct lookup/jmp to the statement. There is no additional hashing that needs to happen. In the case of a String, it precomputes the string hash for the case statements and uses the input String's hashcode to determine where to jump. In the case of collision, it does an if/else chain. Now you might think "This is the same as HashMap, right?" But that isn't true. The hash code for the lookup is computed at compile time and it isn't reduced based on the number of elements (lower chance of collision).
Switches have O(1) lookup, not O(n). (Ok, in truth for a small number of items, switches are turned into if/else statements. This provides better code locality and avoids additional memory lookups. However, for many items, switches are changed into the lookup table I mentioned above).
You can read more about it here
How does Java's switch work under the hood?
It depends:
If there are a few items | fixed items. Using switch if you can ( worst case O(n))
If there are a lot of items OR you want to add future items without modifying much code ---> Using hash-map ( access time is considered as constant time)
You should NOT try to improve performance for the case, because the difference in execution time is nanoseconds. Just focus on readability/maintainability of your code. Is it worth optimizing a simple case to improve a few nanoseconds?
TL/DR
Base it on code readability and maintainability. Both are cost O(1) and provide almost no difference (though switches generally will be slightly faster).
In this particular case a map would be faster, as a switch returns an address and then must go to that address to identify the return value. (A rare case example). If your switch is just calling functions anyways, a Map would also be faster.
To make things faster, I would ensure using numeric cases and avoid using strings via constants or enumerators (typescript).
(edited) I confirmed by expectation: How does Java's switch work under the hood? with switches.
More detailed answer
In the weeds:
A switch statement will usually be higher performance. It creates a lookup table and goto reference and starts at that point. However there are exceptions.
When you utilize a simple switch such as return map.get(x) vs. switch(1=>'a', 2=>'b', etc). That is because the map can directly return the value desired where the switch will stop map the addresses and continue until break or the end is met.
In any event, they should be extremely similar in execution cost.
Think about maintainability and readability of the code
Using a map decouples the data, which can gain the benefit of creating "switch" cases dynamically. More detailed below.
If there are several complex functions/processes you need to handle, it may be easier to read/write if you utilize a map instead. Especially if the switch statement starts to exceed 20 or 30 options.
Personally used case example for maps:
I have been utilize the following pattern for flux (Redux/useReducer) in React applications for some time.
I create a central map where I map the trigger as the key, and the value is a functional reference. I can then load cases where and when it makes sense.
Initially I used this to be able to break the use cases down to reduce file size and group cases of similar function together in a more organized fashion. Although I later evolved it to be loaded in domains and configured the events and data in a domain hook, like useUser, useFeedback, useProfile, etc...
Doing so allowed me to create the default state, initialization functions, events, and so forth into a logical file structure, it also allowed me to keep the footprint low until needed.
One note to keep in mind
Using a map does not allow for drop through, though most people consider this code smell anyways. At the same time it protects from accidental fall through.
In your case, since you are using an Integer key for your HashMap and a plain 'int' for your switch statement, the best performing implementation will be the switch statement unless the number of passes through this section of code is very high (tens or hundreds of thousands).
If I have that kind of example I use Guava ImmutableMaps (sure You can use java 9 builder as well).
private static final Map<String, String> EXAMPLE = ImmutableMaps.<String, String>>builder()
.put("a", "100")
.put("b", "200")
.build();
That way they are immutable and initated only once.
Sometimes I use strategy pattern that way:
private static final Map<String, Command> EXAMPLE = ImmutableMaps.<String, String>>builder()
.put("a", new SomethingCool())
.put("b", new BCool())
.build();
private static final Command DEFAULT= new DefCommand();
Use:
EXAMPLE.getOrDefault("a", DEFAULT).execute(); //java 8
About performance just pick readability. You will thank me later (1 year later) :D.

Assertions in recursive call?

This is a code to check if the graph is bipartite or not. My question is regarding assertions.
I want a check to validate if graph is null or not. Effective java encourages checks even in private functions. Lets say I add an assert graph != null, it would be checked as many times the recursive function is called. This appears inefficient. If the check if done before recursive function is called, then we violate best practices stated in effective java, that every function should validate parameters.Is there some best practice / tradeoff etc? Thanks.
private void dfsBipartiteDetector(Graph graph, int vertex, int i) {
assert graph != null; // <--------- appears inefficient for recursive call.
visited[vertex] = true;
vertexSets.get(i).add(vertex);
final List<Integer> adjList = graph.adj(vertex);
for (int v : adjList) {
if (!visited[v]) {
dfsBipartiteDetector(graph, v, i == 0 ? 1 : 0);
} else {
if (vertexSets.get(i).contains(v)) {
isBipartite = false;
}
}
}
}
Trading efficiency for safety in debug-only code is good practice.
It's pretty common to add quite complex debug-only sanity-checking code, to check the integrity of a whole data structure for instance.
Only if the code slows down so much that it gets in the way of your development process should you think about reducing the amount of such checking.
assert isn't on by default. The check only actually runs if you explicitly enable it by starting the JVM with the -ea option. The idea is to enable assertions while in development, and disable in production to solve the very tradeoff you mention.
Having said that, I find it useful to have such checks on in production, and this is why I prefer using Guava's Preconditions instead of assert keyword, because checks using the former will always run. Performance drop due to this kind of checks are usually negligible compared to other parts of your code, and it can help debugging hard to debug bugs.

Which practice is better (Calling a method from another method multiple times or do the same thing itself)

I have these two methods in my class. The second method does the same thing but for multiple values in tens of thousands (say fifty thousands). So which one is better to go with:
Edit
public static int isUsed(int num) {
if((port < startPort || port > endPort)) {
throw new IllegalArgumentException();
}
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(port);
serverSocket.close();
return false;
} catch (IOException e) {
return true;
}
}
public static int areAllUsed(int arr[]) {
//do the same thing several thousand times >>> Is thisbetters OR
// call isUsed several thousand times >>> this is better
}
With better I mean the memmory or performance.
If you need to reuse a piece of logic in multiple places, defining a function is the best way of reusing the code. Copy-pasting the same logic in another place is not a good idea, because it reduces readability and becomes a maintenance liability in case you must change the logic.
There is little or no performance implications because Java compiler automatically inlines static methods if it finds it beneficial.
DRY is the answer: Don't Repeat Yourself.
If you have the algorithm already coded in isUsed(), then don't reimplement it in another method. Call isUsed().
The JVM is efficient enough to make the difference negligible, or even non-existent, because the isUsed() method will be dynamically inlined into areAllUsed() by the JIT.
In this case, there is a good chance that the method call makes no difference from a performance perspective. For a method that small, there is a good chance that the JIT compiler will inline the method body at the point it is called. (And note that it can do the same thing for non-static final methods, and even non-static, non-final methods in some circumstances.)
The difference in memory usage is trivial.
Either way, it is a generally a bad idea to try to second-guess the compiler / optimizer. It is better to write the code to be readable and maintainable and let the optimizer deal with optimization. If performance is a real concern, then profile your finished code using real / realistic input data ... and use the results of your profiling to determine where you should be directing your effort.
It depends on your application. I will suggest call isUsed several times. The less linear your code is, the easier it is to debugg if there is a problem. If there is a problem, you just need to check isUsed for error.

Is there such a thing as too many embedded if-statements?

Currently I am working on a bit of code which (I believe) requires quite a few embedded if statements. Is there some standard to how many if statements to embed? Most of my googling has turned up things dealing with excel..don't know why.
If there is a standard, why? Is it for readability or is it to keep code running more smoothly? In my mind, it makes sense that it would be mainly for readability.
An example of my if-structure:
if (!all_fields_are_empty):
if (id_search() && validId()):
// do stuff
else if (name_search):
if (name_exists):
if (match < 1):
// do stuff
else:
// do stuff
else if (name_search_type_2):
if (exists):
if (match < 1):
// do stuff
else:
// do stuff
else:
// you're stupid
I have heard that there's a limit to 2-3 nested for/while loops, but is there some standard for if-statements?
Update:
I have some years under my belt now. Please don't use this many if statements. If you need this many, your design is probably bad. Today, I LOVE when I can find an elegant way to do these things with minimal if statements or switch cases. The code ends up cleaner, easier to test, and easier to maintain. Normally.
As Randy mentioned, the cause of this kind of code is in most cases a poor design of an application. Usually I try to use "processor" classes in your case.
For example, given that there is some generic parameter named "operation" and 30 different operations with different parameters, you could make an interface:
interface OperationProcessor {
boolean validate(Map<String, Object> parameters);
boolean process(Map<String, Object> parameters);
}
Then implement lots of processors for each operation you need, for example:
class PrinterProcessor implements OperationProcessor {
boolean validate(Map<String, Object> parameters) {
return (parameters.get("outputString") != null);
}
boolean process(Map<String, Object> parameters) {
System.out.println(parameters.get("outputString"));
}
}
Next step - you register all your processors in some array when application is initialized:
public void init() {
this.processors = new HashMap<String, OperationProcessor>();
this.processors.put("print",new PrinterProcessor());
this.processors.put("name_search", new NameSearchProcessor());
....
}
So your main method becomes something like this:
String operation = parameters.get("operation"); //For example it could be 'name_search'
OperationProcessor processor = this.processors.get(operation);
if (processor != null && processor.validate()) { //Such operation is registered, and it validated all parameters as appropriate
processor.process();
} else {
System.out.println("You are dumb");
}
Sure, this is just an example, and your project would require a bit different approach, but I guess it could be similiar to what I described.
I don't think there is a limit but i wouldn't recommend embeddeding more the two - it's too hard to read, difficult to debug and hard to unit test. Consider taking a look at a couple great books like Refactoring, Design Patterns, and maybe Clean Code
Technically, I am not aware of any limitation to nesting.
It might be an indicator of poor design if you find yourself going very deep.
Some of what you posted looks like it may be better served as a case statement.
I would be concerned with readability, and code maintenance for the next person which really means it will be difficult - even for the first person (you) - to get it all right in the first place.
edit:
You may also consider having a class that is something like SearchableObject(). You could make a base class of this with common functionality, then inherit for ID, Name, etc, and this top level control block would be drastically simplified.
Technically you can have as many as you like but if you have a lot it can quickly make the code unreadable.
What i'd normally do is something like:
if(all_fields_are_empty) {
abuseuser;
return;
}
if(id_search() && validId()) {
//do stuff
return;
}
if(name_search)
{
if(name_exists)
//do stuff
return
else
//do stuff
return
}
I'm sure you get the picture
Tl;Dr You don't really want anymore than 10-15 paths though any one method
What your essentially referring to here is Cyclomatic complexity.
Cyclomatic complexity is a software metric (measurement), used to
indicate the complexity of a program. It is a quantitative measure of
the number of linearly independent paths through a program's source
code. It was developed by Thomas J. McCabe, Sr. in 1976.
So every if statement is potentially a new path though your code and increases it's Cyclomatic complexity. There are tools that will measure this for you and high light areas of high complexity for potential refactoring.
Is there some standard to how many if statements to embed?
Yes and no. It's generally regarded (and McCabe himself argued) that a Cyclomatic complexity of over about 10 or 15 is too high and a sign that the code should be refactored.
One of McCabe's original applications was to limit the complexity of
routines during program development; he recommended that programmers
should count the complexity of the modules they are developing, and
split them into smaller modules whenever the cyclomatic complexity of
the module exceeded 10.[2] This practice was adopted by the NIST
Structured Testing methodology, with an observation that since
McCabe's original publication, the figure of 10 had received
substantial corroborating evidence, but that in some circumstances it
may be appropriate to relax the restriction and permit modules with a
complexity as high as 15. As the methodology acknowledged that there
were occasional reasons for going beyond the agreed-upon limit, it
phrased its recommendation as: "For each module, either limit
cyclomatic complexity to [the agreed-upon limit] or provide a written
explanation of why the limit was exceeded."[7]
This isn't really a hard rule though and can be disregarded in some circumstances. See this question What is the highest Cyclomatic Complexity of any function you maintain? And how would you go about refactoring it?.
why? Is it for readability or is it to keep code running more
smoothly?
Essentially this is for readability, which should make your code run smoothly. To quote Martin Fowler
Any fool can write code that a computer can understand. Good
programmers write code that humans can understand.
The only technical limit to the number of nested if/else blocks in Java will probably be the size of your stack. Style is another matter.
Btw: What's with the colons?

Categories

Resources