Question

Does comparing an int and long hurt performance? i.e.

int x = 1;
long y = 2;
if (x < y) doStuff();

as opposed to:

int x = 1;
int y = 2;
if (x < y) ...

Is there a conversion of types? or does the layout of bits in memory allow a straight comparison? (i.e. the extra bits in the long can all assumed to be 0 for an int)

Was it helpful?

Solution 2

The JLS is a good reference, and makes the requirement for type promotion clear, but no one has talked about the essential question.

At the machine level (post JIT compilation or down deep in the JVM), a processor with a 64-bit ALU will be likely to do the 64- to 32-bit comparison with one instruction to sign-extend the 32-bit operand and a second to do the 64-bit wide comparison followed by a branch around the doStuff call.

For the int to int 32-bit comparison, the sign extension can be omitted. So the difference is one instruction or one cycle for modern cores.

If the machine has a 32-bit ALU, then the 64-bit comparison probably requires 4 instructions: compare, branch, test, branch. But it might be done in 3 (sub with borrow, sub, branch) with the right instructions and/or an extra register.

The int to int requires two: compare and branch. So the difference is 1 or 2 instructions/cycles.

There are very few programs where 1 or 2 cycles make a meaningful performance difference. Use the type you need to ensure your program will work under all contingencies you can imagine over the next decade or so. Forget the couple of cycles.

NB Where 64-bits actually cause a meaningful performance hit is inflating data structure (and to a lesser extent code) sizes by a factor of 2 so that cache and page misses become more frequent. But again you should not worry about this in advance.

Unfortunately Java makes it impossible to alias the unboxed types. A change from int to long or float to double and back is non-trivial: a serious language flaw in many situations.

OTHER TIPS

The Java Language Specification says that binary numeric promotion occurs and the int therefore is converted to a long. In practice the conversion is really trivial - it's not an expensive operation on most modern hardware. However, this whole issue shouldn't really be a performance concern; you use a long not because of performance, but because you need to be able to manage larger numeric values.

And as always with performance questions, the real answer is that:

a) you shouldn't worry about performance until it becomes an issue

b) at that stage you should profile or conduct measurements to see what the effect is.

According to Java language specification, section 5.6.2, binary numeric promotion is performed on the operands of the numerical comparison operators <, <=, >, and >=. This means that int will be promoted to long before the comparison.

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:

  1. If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).
  2. Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

    • If either operand is of type double, the other is converted to double.
    • Otherwise, if either operand is of type float, the other is converted to float.
    • Otherwise, if either operand is of type long, the other is converted to long.
    • Otherwise, both operands are converted to type int.

After the type conversion, if any, value set conversion (§5.1.13) is applied to each operand. Binary numeric promotion is performed on the operands of certain operators:

  • The multiplicative operators *, / and % (§15.17)
  • The addition and subtraction operators for numeric types + and - (§15.18.2)
  • The numerical comparison operators <, <=, >, and >= (§15.20.1)
  • The numerical equality operators == and != (§15.21.1)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top