Let's get ready to ABAP Rumble!
This blog covers a great fight between the ABAP champion Internal Table and challenger Collection. The purpose of the blog is a response to many of the excellent comments received in my previous blog ABAP Trilemma (ABAP Trilemma), such as for example the blog Object Orientation and Performance - Mission Impossible?
Fighter Champion - Internal Table
Internal Table is one of the most used concepts in ABAP programming and needs no further introduction here. More information can be found on help.sap.com.
In this blog, I will use a standard internal table of type MAKT, material descriptions.
Fighter Challenger - Collection
Collection is a very well-known concept in object-oriented languages. It is a dynamic array. More information on Collection can be found here.
At first I wanted to use class CL_OBJECT_COLLECTION for the challenge, but that would be unfair as there is no easy way to retrieve a single object in a collection. Therefore, the challenger is a special type of collection called a map. Unlike the CL_OBJECT_COLLECTION, it is possible to get a single entry by key in the map. This seems more fair compared with the read functionality of the internal table. The map is represented by standard class CL_OBJECT_MAP.
The objects of the collection is a custom class representation of material description. Please note that simply transferring a standard structure into a class is not something that I usually recommend. The purpose here is to be able to compare the Collection with the Internal Table. In real-life the class would span several structures and of course contain methods with logic rather than just get and set methods. I call the class ZCL_MAKT:
Round One - Design
From a design perspective I would prefer using a combination of collection/object instead of internal table/structure. It also follows the official SAP ABAP Guideline DEV-ABAP-2.
Please be aware that I have put no effort into making correct ABAP coding in this blog. The code is optimized so that it is easy to read and understand. Furthermore, I have tried to code in a way that makes the performance results comparable.
Lets have a look at how the coding differs:
Prepare data in the Internal Table or Collection.
Loop or iterate all entries of the Collection or Internal Table.
Update all records of the Collection or Internal Table.
This functionality reads one entry of the Collection or Internal Table.
For the lazy developer, the code can be downloaded as a nugget here.
If you are an OO purist, the winner of Round One is: Collection.
Round Two - Performance and Memory Consumption
I am by no means an expert on ABAP performance and memory analysis. I have simply followed Olga Dolinskaja 's blogs on performance (Next Generation ABAP Runtime Analysis (SAT) – How to analyze performance) and memory analysis (Next Generation ABAP Runtime Analysis (SAT) – How to analyze memory consumption) using transaction SAT. Do not focus on the absolute figures, it is the relation between the Map and Internal Table that counts. Here are the results:
Init Performance and Memory Consumption
The Init part of the performance analysis is the most scary reading of my findings. As you can see the processing time of the Map goes up by a factor 10 everytime the number of records increases by one. That is exponential growth!
Even the processing time of 1000 records is a staggering 13 times longer for the Map than for the Internal Table. For 100000 records it i 167 times longer ... uhh ... 167 times!
You probably think this has to do with my coding. I believe not. It turns out that it is the underlying PUT method of CL_OBJECT_MAP that is the performance bottleneck.
Although Internal Table has lower memory utilization it don't think that it makes a significant difference compared with the performance difference.
Loop Performance and Memory Consumption
The Loop performance of the Map is at least linear when it comes to iterating, but much worse than the Internal Table loop. Actually, the processing time is 27 times longer with 1000 records and 52 times longer with 10000.
The memory utilization is the same as for Init.
Update Performance and Memory Consumption
The Update performance of the Map is also linear, but much worse than the Internal Table loop. Actually, the processing time is 15 times longer for 1000 records and 30 times longer with 10000.
Same as for Init and Loop.
Read Performance and Memory Consumption
The Read performance of the Map is better than the Internal Table However, as you can see the total processing time is low and therefore this advantage will have minor impact on the overall performance. Furthermore, the error tolerance of my unacademic way of testing exceeds the performance difference.
The memory utilization is that same as the previous examples.
The winnder of Round Two is: Internal Table. Depending on your priorities in the ABAP triangle you will either choose Internal Table or Collection. For large data volumes performance is key and therefore the answer is ... Internal Table.