Friday, 14 April 2017

Integer in ABAP, Java and JavaScript

When I first begin to program with ABAP I get confused with different kinds of integer type available for ABAP developers: i, int1, int2, int4, and int8.
According to ABAP help, predefined data types consists of two types:

1. predefined ABAP types: b, c, d, decfloat16, decfloat34, f, i, int8, n, p, s, string, t, x, and xstring.
2. predefined dictionary types: INT1, INT2, INT4, INT8,DEC,DF16_DEC,DF16_RAW,DF34_DEC,DF34_RAW and FLTP.

How to understand the difference between these two types


The predefined dictionary types could be used to define other dictionary datatype:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

However it is not possible to use a predefined ABAP type:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

All these five types could be directly used in ABAP code to define the type of a variable, and i and int4 have the same technical type, see example below:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

Value range of each type


SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

The range of each types could be calculated via formula:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

where n = 2, 4, 8.
For n = 1, since int1 is unsigned char, all the whole 8 bit of 1 byte could be used to represent the numeric value, so the range should then be:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

The constant range of int4 and int8 are defined in class CL_ABAP_MATH:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

while int1 and int2 are defined in another class CL_ABAP_EXCEPTIONAL_VALUES:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

Integer and RTTI


Test via the following code:
DATA: lv1 TYPE i VALUE 1,
      lv2 TYPE int1 VALUE 1,
      lv3 TYPE int2 VALUE 1,
      lv4 TYPE int4 VALUE 1,
      lv5 TYPE int8 VALUE 1.

DATA: lv1_copy TYPE i VALUE 2,
           lv2_copy TYPE int1 VALUE 2.

DATA(lo1) = cl_abap_typedescr=>describe_by_data( lv1 ).
DATA(lo2) = cl_abap_typedescr=>describe_by_data( lv2 ).
DATA(lo3) = cl_abap_typedescr=>describe_by_data( lv3 ).
DATA(lo4) = cl_abap_typedescr=>describe_by_data( lv4 ).
DATA(lo5) = cl_abap_typedescr=>describe_by_data( lv5 ).

DATA(lo1_copy) = cl_abap_typedescr=>describe_by_data( lv1_copy ).
DATA(lo2_copy) = cl_abap_typedescr=>describe_by_data( lv2_copy ).

Result shows that lo1 and lo1_copy point to the same element descriptor reference since they are both performed on variable with the same type i.
The same holds true for lo2 and lo2_type ( int1 ).
Although i and int4 have the same technical type, however since their absolute type are different, so different descriptor reference are returned ( lo1 and lo4 ).

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

Value comparison and reference comparison


It is not difficult to forecast the result of test below:

DATA: lv_i1 TYPE i VALUE 1,
      lv_i2 TYPE int4 VALUE 1,
      lv_i3 TYPE int8 VALUE 1,
      lv_i4 TYPE int4 VALUE 1.

WRITE: / 'l1 = l2?' , boolc( lv_i1 EQ lv_i2 ).
WRITE: / 'l1 = l3?' , boolc( lv_i1 EQ lv_i3 ).
WRITE: / 'l2 = l3?' , boolc( lv_i2 EQ lv_i3 ).

DATA: lo_i1 TYPE REF TO i,
      lo_i2 TYPE REF TO int1,
      lo_i3 TYPE REF TO int2.

lo_i1 = NEW #( 1 ).
lo_i2 = NEW #( 1 ).
lo_i3 = NEW #( 1 ).

WRITE: / 'o1 = o2?' , boolc( lo_i1 EQ lo_i2 ).
WRITE: / 'o1 = o3?' , boolc( lo_i1 EQ lo_i3 ).
WRITE: / 'o2 = o3?' , boolc( lo_i2 EQ lo_i3 ).

WRITE: / 'o1->* = o2->* ?' , boolc( lo_i1->* EQ lo_i2->* ).
WRITE: / 'o1->* = o3->* ?' , boolc( lo_i1->* EQ lo_i3->* ).
WRITE: / 'o2->* = o3->* ?' , boolc( lo_i2->* EQ lo_i3->* ).

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

Integer in Java


Before we start the explore in Java, see the following crazy code:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

Yes, 2 + 2 = 5 in Java?!

Before I unveil the source code of method doSomethingMagic,
let’s first see another example which is easier to understand.
I perform the accumulation from 0 to 10000 and repeat it for 10000 times. I did this operation twice with different approaches: calc1 and calc2. The logic inside the two methods are exactly the same except that different types are used for iterator variable i and variable to store add result in each loop.
public class IntegerCompare {

private static long start;
private static void start(){
start = System.currentTimeMillis();
}
private static long end(){
return System.currentTimeMillis() - start;
}
private static final int NUM = 10000;
private static int calc1(){
Integer result = 0;
for( Integer i = 0; i < NUM; i++){
result += i;
}
return result;
}
private static int calc2(){
int result = 0;
for( int i = 0; i < NUM; i++){
result += i;
}
return result;
}
public static void main(String[] args) {
System.out.println("Calc1: " + calc1());
System.out.println("Calc2: " + calc2());
start();
for( int i = 0; i < NUM; i++){
calc1();
}
System.out.println("Calc1 time: " + end());
start();
for( int i = 0; i < NUM; i++){
calc2();
}
System.out.println("Calc2 time: " + end());
}
}

The printed time shows that the second approach has much better performance than the first.

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

Decompile the .class file and we can know the reason of this performance difference. In the first solution, there are lots of object instance method call intValue and static method call Integer.valueOf which are much expensive compared with operations against primitive type int.

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

There is so called Autoboxing and unboxing in Java Specification.  Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example when you write the following code:

Integer a = 10; 

Decompile the .class file and we find that Java compiler translate the code into:

Integer a = Integer.valueOf(10);

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

It is the very huge amount of Autoboxing operations in the first approach which leads to a poor performance compared with the second solution.

Why 2 + 2 = 5?

Now it’s time to go back to the mysterious method doSomethingMagic in the example.
First check how Integer.valueOf is implemented in JDK. Nothing special there, ABAPer should be very familiar with such style: first check whether the primitive value to be boxed has already corresponding buffered instance in IntegerCache.cache ( just consider it as an internal table in ABAP ). If buffer hits, directly return the entry, otherwise instantiate a new boxed instance. By default the buffer logic only cover the range -128 ~ 127.

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

Now let’s see the source code of doSomethingMagic, where one entry in Integer buffer maintained by IntegerCache.cache is modified by reflection.

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

The 132nd entry, which originally represents for primitive value 4, is now overwritten by 133rd entry ( primitive value 5 ).
And 2 + 2 is actually converted by Compiler as Integer.valueOf(4) in compilation time:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

So finally “5” is returned as the result of Integer.valueOf(4):

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

Last but not the least, in ABAP we have similar utility method as Integer.valueOf in Java which converts the input Char like value into a real INT8 value.

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

Integer in JavaScript


Since now we already the knowledge of Autoboxing and unboxing, it is pretty easy to understand the logic in JavaScript as well.
In Java it is not possible to perform any method call on an variable with primitive type:

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

However it is possible in JavaScript. Check the examples below, where the autoboxing occurs – an new Number object is created under the hood.

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide

SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP ABAP Guide
(1).toString() equals to code below:

var a = new Number(1);
a.toString();

No comments:

Post a Comment