Java Ternary vs. if with big objects - java

The ternary operator normally just is a subject to philosophical discussions:
whether
a=b>5?1:0;
is more readable, faster, cooler to
if(b>5) { a=1; } else {a=0;}
(take or leave the curly braces) I normally don't care. I like my ternary operator. But we had a discussion concerning this piece of code:
BigObject myBigObject=null;
...
do {
myBigObject=
myBigObject==null?
createBigObject():
myBigObject;
...
} while(manyIteration);
Colleague claimed that this construct will create the myBigObject will be copied every loop (except the first) which will waste precious time and memory
and that he found the case where the ternary operator is useless. the only way is:
do {
if(myBigObject==null)
myBigObject=createBigObject();
...
} while(manyIteration);
I argued that the clever compiler will see that the object is assigned to itself and will optimize it out.
But who is right?

The definite answer lies in section 15.25 of the JLS (emphasis mine):
The resulting boolean value is then used to choose either the second or the third operand expression:
- If the value of the first operand is true, then the second operand expression is chosen.
- If the value of the first operand is false, then the third operand expression is chosen.
The chosen operand expression is then evaluated and the resulting value is converted to the type of the conditional expression as determined by the rules stated below.
This conversion may include boxing or unboxing conversion (§5.1.7, §5.1.8).
The operand expression not chosen is not evaluated for that particular evaluation of the conditional expression.
This means both expressions are not always evaluated: only the one that needs to be is. So actually, none of you are right.
You're wrong because it is not the compiler being clever: it is specified by the language itself;
Your collegue is wrong because the expression won't be evaluated if need not be.
In the code
myBigObject = myBigObject == null ? createBigObject() : myBigObject;
^-----------------^ ^---------------^
this is true the 1st time, hence that ^ is evaluated
myBigObject = myBigObject == null ? createBigObject() : myBigObject;
^-----------------^
this is false the 2nd time, hence that ^ is NOT evaluated, that ^ is
Notice that what is executed is just assigning myBigObject to itself, which does not create a new object.

Colleague claimed that this construct will create the myBigObject will be copied every loop (except the first) which will waste precious time and memory and that he found the case where the ternary operator is useless.
You should note that myBigObject is a reference to an object. This means it is 4 bytes on most JVMs and a redundant copy isn't going to make a big difference.
I argued that the clever compiler will see that the object is assigned to itself and will optimize it out.
Possibly, though I don't see it will make much difference either way.
While a compiler can remove redundant code, it is harder for a human to remove redundant code. In general we code with a purpose. When code has no purpose it is much harder to come to that conclusion. I suggest you avoid confusing anyone who has to read/maintain the code in the future.
As ever, when discussing performance, you should first consider clarity. How surprising in this construct and how easy is it to maintain.
The cost of a redundant assignment (which may or may not be optimised away) is nothing compared with the cost of even an easy to fix bug (never mind a hard to fix one)
You should focus on what is clearer (which is subjective) and not worry about micro-tuning the code unless you have a profiler which indicates this line is a performance issue.
For me, this is clearer, but even if it were slower, I would still argue it is clearer and easier to understand what it is doing.
if (myBigObject == null)
myBigObject = createBigObject();
The fact you have already had to have a discussion but what that code is really doing, means you have spent more time than you can possibly recover.
In short, developer efficiency is usally more important than computer efficiency.

Your colleague is wrong. After the first iteration myBigObject is no longer null and hence won't be created. Sample code proves this...
public static void main(String[] args) {
Object myBigObject=null;
int i=0;
do {
System.out.println("Iteration " + i);
myBigObject=
myBigObject==null?
createBigObject():
myBigObject;
} while(i++ < 10);
}
private static Object createBigObject() {
System.out.println("Creating bigObject");
return new Object();
}
The output of which is
Iteration 0
Creating bigObject
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
Iteration 6
Iteration 7
Iteration 8
Iteration 9
Iteration 10
See how the create statement is only printed once

Why does your colleague think that?
Only exactly one branch of a ternary conditional is ever evaluated. Imagine if it were not the case? So much code of the form obj == null ? null : obj.someproperty() would break!
So your object will only be created once.

Related

Can anyone explain why the outputs are different in C and Java?

{
public static void main(String[] args) {
int a = 10;
if (a == a--)
System.out.println("first\t");
a=10;
if(a==--a)
System.out.println("second\t");
}
}
For the java program, output is "first", whereas for the C/C++ program its "second". The functionality of post/pre fix operations are same in both programs to my knowledge. If anyone can shed some light on the logic, it would be great as I am new to coding.
int main()
{
int a = 10;
if(a==a--)
printf("first\t");
a=10;
if(a==--a)
printf("second\t");
}
In java, you get the guarantee that you'll always observing this code printing First, and never Second.
In C/C++, you get no such guarantees. Depending on compiler, architecture, OS, and phase of the moon, it will likely print either only First or Second but I'm pretty sure the C and C++ spec make it 'legal' for a compiler/architecture/OS/phase-of-moon combo to end up printing BOTH First and Second or even neither.
See order of evaluation rules for C++: Given some binary operator construct: a x b where a and b are expressions and x is some binary operator, then first a and b must be evaluated, and then the x operator is applied to the values so obtained. Unless the operator explicitly decrees an order (which for example the || and && operators do; they promise to short-circuit, that is, to not evaluate b at all, if a is such b cannot affect the result) - then a C(++) compiler is free to emit code such that b is evaluated before a is, or vice versa.
C is filled to the brim with such 'shoulds' and 'mays': The C spec is designed to allow C code to compile on a wide variety of chips with a ton of leeway for a compiler to apply far-reaching optimizations. It goes so far that simple primitive data types have an unspecified bitwidth.
Contrast to java, where almost everything is locked down: There are very few aspects of java code which are intentionally left unspecified, and the compiler is 'on rails' and is very very limited in what bytecode it is allowed to emit (in java, the optimizations are left to the runtime / hotspot compiler, not to javac).
That's why, on java, the spec DOES define explicitly precisely how a x b ought to be resolved: the java spec does decree that regardless of operator, a must always be evaluated before b is evaluated (unless, just like in C, b isn't evaluated at all due to short-circuit rules).
Going all the way back to the Java Language Specification v7, the spec explicitly dictates the left hand side MUST be evaluated first - and this hasn't changed since then (and I'm pretty sure was true since java 1.0, for what it's worth. It's probably chapter 15.7.1 in most JLS versions).
In C and C++, the behavior of the expressions a == a-- and a == --a is undefined:
6.5 Expressions
...
2 If a side effect on a scalar object is unsequenced relative to either a different side effect
on the same scalar object or a value computation using the value of the same scalar
object, the behavior is undefined. If there are multiple allowable orderings of the
subexpressions of an expression, the behavior is undefined if such an unsequenced side
effect occurs in any of the orderings.84)
84) This paragraph renders undefined statement expressions such asi = ++i + 1;
a[i++] = i;
while allowingi = i + 1;
a[i] = i;
C 2011 Online Draft
C does not force left-to-right evaluation of relational and equality expressions, and it does not require that the side effect of the -- and ++ operators be applied immediately after evaluation. The result of a == a-- can vary based on the compiler, hardware, even the surrounding code.
Java, OTOH, does force left-to-right evaluation and applies side effects immediately after evaluation, so the result is consistent and well-defined.
In C (as the code in the second example seems to be),
The evaluation order of the subexpressions is unspecified, and
There is no sequence point between the operands of the == operator.
Thus, If the increment of a in if (a == a++) or decrement of a in if (a == a--) happens before the comparison to a itself is not defined.
The result invokes undefined behavior. It could give different results already at the next execution on the same machine.
In contrary, Java seems to define this behavior.

Fast constant time evaluation of "x==7" to 1 (true) or 0 (false) in Java

I want to port a crypto function from C to Java. The function has to run in constant time, so no conditional branchings (and no table lookups based on x) are allowed.
The original C code is:
int x,result;
...
result = (x==7);
...
So that 'result' is set to 1 if 'x==7' and to 0 otherwise. The 'result' variable is then used in further computations.
I am now looking for the best way to transpose this to Java. As in Java expressions evaluate to booleans and not to integers, one has to simulate the above using operators.
I currently use
int x,result;
...
result = (1<<(x-7))&1;
...
which works fine for me, as my x is in the range {0,...,15}. (Note that the shift function uses only the lower 5 bits, so that you will get false positives when x is too large.)
The expression will be evaluated millions of times, so if it there is for instance a clever solution that uses only 2 operators instead of 3, this would make the overall computation faster.
The best option as noted by #Hosch250 is ternary operator. Let's take a look at the assembler generated by JIT compiler for this method:
public static int ternary(int x) {
return x == 7 ? 1 : 0;
}
It actually depends on branch profiling. When your x has value 7 quite often, it's compiled like this:
xor %r11d,%r11d
mov $0x1,%eax
cmp $0x7,%edx
cmovne %r11d,%eax ;*ireturn
; - Test::ternary#11 (line 12)
See that ternary was replaced with cmovne which is not the branch instruction.
On the other hand if you pass 7 in very rare cases (e.g. once in 5000 calls), then branch is here:
cmp $0x7,%edx
je <slowpath> ;*if_icmpne
; - Test::ternary#3 (line 12)
xor %eax,%eax
Now branch is almost never taken, so the faster is to keep the condition as CPU branch predictor will be almost always correct. Note that <slowpath> is not just return 1;, it also updates the branch profile, so if it happens that the pattern changed during the program execution (7 become to appear more often), then the method will be recompiled to the first version.
In general, don't try to be smarter than JIT-compiler in such simple cases.
OK, so I think that the reason you are asking this is that if the execution time of a crypto function depends on the inputs to the function, then an attacker can gain clues as to those inputs by measuring the execution time. (Hence, the normal "premature optimization" and "don't try to outsmart the compiler" advice don't really apply.)
In the light of that, here are my suggestions:
If x is a constant at compile time (or JIT compile time) then the chances are that the code will be optimized to either
result = true; or result = false;
If x is not a constant, but there is a small range of possible values then one of the following approaches will probably work:
// It is possible but unlikely that the JIT compiler will
// turn this into conditional code.
private boolean[] LOOKUP = new boolean[] {
true, true, true, true, true, true, true, false};
...
result = LOOKUP[x];
// This depends on how the JIT compiler translates this to native
// code.
switch (x) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6:
result = false;
case 7:
result = true;
}
The problem is that in every possible approach I can think of, the JIT compiler could legally optimize non-branching code into branching code. If this is security critical, then you need to investigate the actual native code emitted for every platform that you need to certify.
The other approach is to:
analyze the Java code algorithm,
try to spot cases where conditional branching is likely,
design test inputs to trigger those branching paths,
measure execution time (on all target platforms) to see if there is a detectable difference across your set of test inputs.
Of course, the other thing to note is that this may be moot anyway; e.g. if result is then used in another part of the crypto function to decide with execution path to take.
And ...
The expression will be evaluated millions of times, so if it there is for instance a clever solution that uses only 2 operators instead of 3, this would make the overall computation faster.
If this is your real motivation ... then my advice is Don't Bother. This is premature optimization. Leave it to the JIT compiler.
Since the goal is to accomplish
if (x == 7)
result = 1;
else
result = 0;
in some sort of algebraic fashion without branching,
result = 1 >> (x^7);
But then this does not work because right shift is masked to only a few bits. So, what you can do is,
result = 1 >> Integer.bitCount(x^7);
but it's still masked for case of -6 (all bits set in case of -6 ^ 7), so,
int bc = Integer.bitCount(x^7);
return 1 >> (bc | (bc>>1));
So, how much slower is it than a branch conditional? Above solution using bitCount(), to compare entire range int range more than once,
user 0m5.948s
Using branching, (x == 7 ? 1 : 0),
user 0m2.104s
So it's not too bad considering you get constant time comparison that works for any value, 7 being just an example. Yes, Integer.bitCount() is constant time too.
A ternary would be a good option here:
result = x == 7 ? 1 : 0;
This code assigns 1 to result if the expression x == 7 evaluates to true, and assigns 0 otherwise.
Taking advantage of the extremely limited range of x, which is in [0,15], I propose using an in-register table lookup, using one bit per table entry. The table has bit i set for those inputs that should produce a 1, and zero otherwise. This means our table is the literal constant 27 = 128:
int x,result;
result = (128 >> x) & 1;

checking if a string is interleaving of two other strings

I came across multiple links to the solution of the problem - "How to check if a string is interleaving of two other strings"
Two solutions looked particularly interesting to me which work but I have doubts in both of them.
FIRST I did not get the hashing part in this where author is saying "A pure recursive solution will cause time limit exceed. We can optimize it by caching the false visited solutions in the visited set. That will short circuit many repeated search path"
SECOND I did not the the "else condition" on line 18 in recursive. Won't one of the conditions (line 14th and line 16th) will always be true as they are inside else of line 11th if condition which is if(s2.charAt(0) != s3.charAt(0) && s1.charAt(0) != s3.charAt(0)) {
First
This is actually space-time tradeoff (the computation time can be reduced at the cost of increased memory use). Why does the author say pure recursive solution slow (in fact it's exponential time complexity)? It comes from repeated recursion and because of that, it computes the same values again and again.
So what can you do? You can store the value you already computed. Next time you want this value again, just look up in a table. This is called caching, when the values are cached, you can treat every recursive call inside the function as it would run in O(1) time complexity. The core idea is don't calculate the same things twice.
Second
In the case s2.charAt(0) == s3.charAt(0) && s1.charAt(0) == s3.charAt(0).

When does it make sense to store the result of a comparison versus recalculating a comparison in terms of speed?

I'd like to have a solid understanding of when (ignoring available memory space) it makes sense to store the result of a comparison instead of recalculating it. What is the tipping point for justifying the time cost incurred by storage? Is it 2, 3, or 4 comparisons? More?
For example, in this particular case, which option (in general) will perform better in terms of speed?
Option 1:
int result = id.compareTo(node.id);
return result > 0 ? 1 : result < 0 ? -1 : 0;
Option 2:
return id.compareTo(node.id) > 0 ? 1 : id.compareTo(node.id) < 0 ? -1 : 0;
I tried to profile the two options myself in order to answer my own question, but I don't have much experience with this sort of performance testing and, as such, would rather get a more definitive answer from someone with either more experience or else a better grasp of the theoretical elements involved.
I know it's not a big deal and that most of the time the difference will be negligible. However, I'm a perfectionist, and I'd really just like to resolve this particular issue so that I can get on with my life, haha.
Additionally, I think the answer is likely to prove enlightening in regards to similar situations I may encounter in the future wherein the difference might very well be significant (such as when the cost of a comparison or memory allocation is either unable to be incurred or else complex enough to cause a real issue concerning performance).
Answers should be relevant to programming with Java and not other languages, please.
I know I've mentioned it a few times already, but PLEASE focus answers ONLY on the SPEED DIFFERENCE! I am well aware that many other factors can and should be taken into account when writing code, but here I want just a straight-forward argument for which is FASTER.
Experience tells me that option 1 should be faster, because you're making just one call to the compare method and storing the result for reuse. Facts that support this belief are that local variables live on the stack and making a method call involves a lot more work from the stack than just pushing a value onto it. However profiling is the best and safest way to compare two implementations.
The first thing to realise is that the java compiler and JVM together may optimise your code how it wishes to get the job done most efficiently (as long as certain rules are followed). Chances are there is no difference in performance, and chances are also that what is actually executed is not what you think it is.
One really important difference however is in debugging: if you put a break point on the return statement for the store-in-variable version, you can see what was returned from the call, otherwise you can't see that in a debugger. Even more handy is when you seemingly uselessly store the value to be returned from the method in a variable, then return it, so you may see what's going to be returned from a method while debugging, otherwise there's no way to see it.
Option 1 cannot be slower than 2, if the compiler optimizes then both could be equal, but then still 1) is more readable, compacter, and better testable.
So there is no argument for Option 2).
If you like you could change to final int result = ....
Although i expect that the compiler is so clever that the final keyword makes no difference in this case, and the final makes the code a bit less readable.
option1 one always preferred one ,because here the real world scenarion
----->ok lets
1) thread exceution at id.compareTo(node.id) > 0 ? 1 , in this process some other thread
changes the value of node.id right after id.compareTo(node.id) > 0 ? 1 before going to
id.compareTo(node.id) < 0 ? -1 : 0 this check , the result not identical?
performance wise option1 has more performance when there is bit of functionality exisist in checking.
When does it make sense to store the result of a comparison versus recalculating a comparison in terms of speed?
Most of the time, micro-optimizations like option #1 versus option #2 don't make any significant difference. Indeed, it ONLY makes a significant performance difference if:
the comparison is expensive,
the comparison is performed a large number of times, AND
performance matters.
Indeed, the chances are that you have alrady spent more time and money thinking about this than will be saved over the entire useful lifetime of the application.
Instead of focussing on performance, you should be focussing on making your code readable. Think about the next person who has to read and modify the code, and make it so that he/she is less likely to misread it.
In this case, the first option is more readable than the second one. THAT is why you should use it, not performance reasons. (Though, if anything, the first version is probably faster.)

Why is there a prefix/postfix ++ but no prefix/postfix +=?

This may seem like a silly question, but why is it that in many languages there exists a prefix and postfix version of the ++ and -- operator, but no similar prefix/postfix versions of other operators like += or -=? For example, it seems like if I can write this code:
myArray[x++] = 137; // Write 137 to array index at x, then increment x
I should be able to write something like
myArray[5 =+ x] = 137; // Write 137 to array index at x, then add five to x
Of course, such an operator does not exist. Is there a reason for this? It seems like a weird asymmetry in C/C++/Java.
I'd guess there are several reasons, I think among the more heavily weighted might be:
there probably weren't thought to be too many real use cases (it may not have even occurred to some language designers in the early days)
pre/post increment mapped directly to machine operations (at least on several machines), so they found their way into the language (update: it turns out that this isn't exactly true, even if it's commonly thought so in computing lore. See below).
Then again, while the idea for pre/post/increment/decrement operators might have been influenced by machine operations, it looks like they weren't put into the language specifically to take advantage of such. Here's what Dennis Ritchie has to say about them:
http://cm.bell-labs.com/cm/cs/who/dmr/chist.html
Thompson went a step further by inventing the ++ and -- operators, which increment or decrement; their prefix or postfix position determines whether the alteration occurs before or after noting the value of the operand. They were not in the earliest versions of B, but appeared along the way. People often guess that they were created to use the auto-increment and auto-decrement address modes provided by the DEC PDP-11 on which C and Unix first became popular. This is historically impossible, since there was no PDP-11 when B was developed. The PDP-7, however, did have a few `auto-increment' memory cells, with the property that an indirect memory reference through them incremented the cell. This feature probably suggested such operators to Thompson; the generalization to make them both prefix and postfix was his own. Indeed, the auto-increment cells were not used directly in implementation of the operators, and a stronger motivation for the innovation was probably his observation that the translation of ++x was smaller than that of x=x+1.
As long as y has no side effects:
#define POSTADD(x,y) (((x)+=(y))-(y))
I'll make an assumption. There're lots of use-cases for ++i/i++ and in many the specific type of increment (pre/post) makes difference. I can't tell how many times I've seen code like while (buf[i++]) {...}. On the other hand, += is used much less frequently, as it rarely makes sense to shift pointer by 5 elements at once.
So, there's just no common enough application where difference between postfix and prefix version of += would be important.
I guess it's because it's way too cryptic.
Some argue that even ++/-- should be avoided, because they cause confusion and are responsible for most buffer overrun bugs.
Because the -- and ++ operators map to inc(rement) and dec(rement) instructions (in addition to adding and subtracting) in the CPU, and these operators are supposed to map to the instructions, hence why they exist as separate operators.
Java and C++ have pre- and post- increment and decrement operators because C has them. C has them because C was written, mostly, for the PDP-11 and the PDP-11 had INC and DEC instructions.
Back in the day, optimizing compilers didn't exist so if you wanted to use a single cycle increment operator, either you wrote assembler for it or your language needed an explicit operator for it; C, being a portable assembling language, has explicit increment and decrement operators. Also, the performance difference between ++i and i++ rarely matters now but it did matter in 1972.
Keep in mind that C is almost 40 years old.
If I had to guess, it's common to equate:
x += 5;
...with:
x = x + 5;
And for obvious reasons, it would be nonsensical to write:
x + 5 = x;
I'm not sure how else you would mimic the behavior of 5 =+ x using just the + operator. By the way, hi htiek!

Categories