This is a test message to test the length of the message box.
Login
ABAP Quick Performance Chained statement
Created by Software-Heroes

ABAP Quick - Performance chained statements

413

Let's take a look at the performance when creating chained statements with DATA and FIELD-SYMBOL. Which variant will be ahead in terms of performance?



Not long ago we were in contact with a colleague who had already worked directly on projects at SAP. There he was told never to represent data declarations in chained statements, as this would suffer performance. Let's do a little experiment and measure both shapes.

 

Introduction

What are sets of chains and how are they formed? There are some statements in the ABAP programming language that can be used to build sentences without repeating the actual keyword. To do this, place a colon after the statement and carry out the same action over and over again, separating the elements with a comma. Here's an example:

" Chained statement
DATA:
  ld_stream  TYPE xstring,
  ld_comment TYPE string,

" Single use  
DATA ld_stream  TYPE xstring.
DATA ld_comment TYPE string.  

 

The advantage of a chain statements is that you save on coding because you can omit the keyword. Such statements are usually automatically formatted by the Pretty Printer.

 

Preparation

In order to follow up the statement and create a good test, we first prepare some structures and data types that we then use for our test case.

TYPES:
  td_simple_text   TYPE c LENGTH 40,
  td_simple_number TYPE p LENGTH 15 DECIMALS 2,

  BEGIN OF ts_flat_structure,
    key    TYPE td_simple_text,
    text   TYPE string,
    number TYPE i,
  END OF ts_flat_structure,
  tt_flat_standard TYPE STANDARD TABLE OF ts_flat_structure WITH EMPTY KEY,
  tt_flat_sorted   TYPE SORTED TABLE OF ts_flat_structure WITH UNIQUE KEY key,

  BEGIN OF ts_key_value,
    key   TYPE string,
    value TYPE string,
  END OF ts_key_value,
  tt_key_standard TYPE STANDARD TABLE OF ts_key_value WITH EMPTY KEY,
  tt_key_sorted   TYPE SORTED TABLE OF ts_key_value WITH UNIQUE KEY key,

  BEGIN OF ts_deep,
    key       TYPE string,
    key_value TYPE tt_key_sorted,
    flat      TYPE tt_flat_sorted,
  END OF ts_deep,
  tt_deep_standard TYPE STANDARD TABLE OF ts_deep WITH EMPTY KEY,
  tt_deep_sorted   TYPE SORTED TABLE OF ts_deep WITH UNIQUE KEY key,

  BEGIN OF ts_too_deep,
    key        TYPE string,
    structure1 TYPE ts_deep,
    structure2 TYPE ts_deep,
    table1     TYPE tt_deep_standard,
    table2     TYPE tt_deep_sorted,
  END OF ts_too_deep,
  tt_too_deep_standard TYPE STANDARD TABLE OF ts_too_deep WITH EMPTY KEY,
  tt_too_deep_sorted   TYPE SORTED TABLE OF ts_too_deep WITH UNIQUE KEY key.

 

To do this, we first define some simple types and then it becomes more and more complex and deep types, since we assume that the process of creating complex types will take longer.

 

Test case

In our test, we want to validate the data declaration for DATA and FIELD-SYMBOL, since these are the most common options. The test cases now look like we first generate some data as a chain set and then in the next step we generate the same data on a single level. We then run these routines x times in order to make differences between them measurable. Finally, the result is written to the console:

GET TIME STAMP FIELD ld_start.
DO c_run_count TIMES.
  data_creation_in_one_statement( ).
ENDDO.
GET TIME STAMP FIELD ld_end.
out->write( |DATA - One Statement: { ld_end - ld_start }| ).

 

DATA

In the two methods, we generate a series of simple and increasingly complex types. We assume that more complex data types take longer in time because more memory needs to be allocated:

METHOD data_creation_in_one_statement.
  DATA:
    ld_text              TYPE td_simple_text,
    ld_stream            TYPE xstring,
    ld_comment           TYPE string,
    ld_value             TYPE i,
    ld_currency          TYPE td_simple_number,
    lt_flat_standard     TYPE tt_flat_standard,
    lt_flat_sorted       TYPE tt_flat_sorted,
    lt_key_standard      TYPE tt_key_standard,
    lt_key_sorted        TYPE tt_key_sorted,
    lt_deep_standard     TYPE tt_deep_standard,
    lt_deep_sorted       TYPE tt_deep_sorted,
    lt_too_deep_standard TYPE tt_too_deep_standard,
    lt_too_deep_sorted   TYPE tt_too_deep_sorted.
ENDMETHOD.


METHOD data_creation_many_statements.
  DATA ld_text              TYPE td_simple_text.
  DATA ld_stream            TYPE xstring.
  DATA ld_comment           TYPE string.
  DATA ld_value             TYPE i.
  DATA ld_currency          TYPE td_simple_number.
  DATA lt_flat_standard     TYPE tt_flat_standard.
  DATA lt_flat_sorted       TYPE tt_flat_sorted.
  DATA lt_key_standard      TYPE tt_key_standard.
  DATA lt_key_sorted        TYPE tt_key_sorted.
  DATA lt_deep_standard     TYPE tt_deep_standard.
  DATA lt_deep_sorted       TYPE tt_deep_sorted.
  DATA lt_too_deep_standard TYPE tt_too_deep_standard.
  DATA lt_too_deep_sorted   TYPE tt_too_deep_sorted.
ENDMETHOD.

 

FIELD-SYMBOL

With the field symbols, we deliberately rely on the same generation of the data in order to be able to ensure that they can be compared with one another.

METHOD fld_creation_in_one_statement.
  FIELD-SYMBOLS:
    <ld_text>              TYPE td_simple_text,
    <ld_stream>            TYPE xstring,
    <ld_comment>           TYPE string,
    <ld_value>             TYPE i,
    <ld_currency>          TYPE td_simple_number,
    <lt_flat_standard>     TYPE tt_flat_standard,
    <lt_flat_sorted>       TYPE tt_flat_sorted,
    <lt_key_standard>      TYPE tt_key_standard,
    <lt_key_sorted>        TYPE tt_key_sorted,
    <lt_deep_standard>     TYPE tt_deep_standard,
    <lt_deep_sorted>       TYPE tt_deep_sorted,
    <lt_too_deep_standard> TYPE tt_too_deep_standard,
    <lt_too_deep_sorted>   TYPE tt_too_deep_sorted.
ENDMETHOD.


METHOD fld_creation_many_statements.
  FIELD-SYMBOLS <ld_text>              TYPE td_simple_text.
  FIELD-SYMBOLS <ld_stream>            TYPE xstring.
  FIELD-SYMBOLS <ld_comment>           TYPE string.
  FIELD-SYMBOLS <ld_value>             TYPE i.
  FIELD-SYMBOLS <ld_currency>          TYPE td_simple_number.
  FIELD-SYMBOLS <lt_flat_standard>     TYPE tt_flat_standard.
  FIELD-SYMBOLS <lt_flat_sorted>       TYPE tt_flat_sorted.
  FIELD-SYMBOLS <lt_key_standard>      TYPE tt_key_standard.
  FIELD-SYMBOLS <lt_key_sorted>        TYPE tt_key_sorted.
  FIELD-SYMBOLS <lt_deep_standard>     TYPE tt_deep_standard.
  FIELD-SYMBOLS <lt_deep_sorted>       TYPE tt_deep_sorted.
  FIELD-SYMBOLS <lt_too_deep_standard> TYPE tt_too_deep_standard.
  FIELD-SYMBOLS <lt_too_deep_sorted>   TYPE tt_too_deep_sorted.
ENDMETHOD.

 

Execution

In order to be able to carry out a comparison, we start the logic several times and rely on a loop run of 100000 runs. In practice, this means the routine is called that many times. This could be compared to a central building block of a processing chain, where processing is called up so often. Here is the output in the console:

 

What do the numbers mean in detail? If we compare the individual statements with each other, the numbers are quite similar, sometimes the individual statements are slower, sometimes the chain statement as well. Therefore, how our data is declared made no difference to the overall runtime of a program or processing. However, if we take a look at the performance between DATA and FIELD-SYMBOL, we see a bigger difference. Field symbols are clearly made available faster.

 

Full example

At the end of the article, the entire example so that you can recreate the experiment on your own.

CLASS zcl_bs_demo_performance_data DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PROTECTED SECTION.
  PRIVATE SECTION.
    TYPES:
      td_simple_text   TYPE c LENGTH 40,
      td_simple_number TYPE p LENGTH 15 DECIMALS 2,

      BEGIN OF ts_flat_structure,
        key    TYPE td_simple_text,
        text   TYPE string,
        number TYPE i,
      END OF ts_flat_structure,
      tt_flat_standard TYPE STANDARD TABLE OF ts_flat_structure WITH EMPTY KEY,
      tt_flat_sorted   TYPE SORTED TABLE OF ts_flat_structure WITH UNIQUE KEY key,

      BEGIN OF ts_key_value,
        key   TYPE string,
        value TYPE string,
      END OF ts_key_value,
      tt_key_standard TYPE STANDARD TABLE OF ts_key_value WITH EMPTY KEY,
      tt_key_sorted   TYPE SORTED TABLE OF ts_key_value WITH UNIQUE KEY key,

      BEGIN OF ts_deep,
        key       TYPE string,
        key_value TYPE tt_key_sorted,
        flat      TYPE tt_flat_sorted,
      END OF ts_deep,
      tt_deep_standard TYPE STANDARD TABLE OF ts_deep WITH EMPTY KEY,
      tt_deep_sorted   TYPE SORTED TABLE OF ts_deep WITH UNIQUE KEY key,

      BEGIN OF ts_too_deep,
        key        TYPE string,
        structure1 TYPE ts_deep,
        structure2 TYPE ts_deep,
        table1     TYPE tt_deep_standard,
        table2     TYPE tt_deep_sorted,
      END OF ts_too_deep,
      tt_too_deep_standard TYPE STANDARD TABLE OF ts_too_deep WITH EMPTY KEY,
      tt_too_deep_sorted   TYPE SORTED TABLE OF ts_too_deep WITH UNIQUE KEY key.

    CONSTANTS:
      c_run_count TYPE i VALUE 100000.

    METHODS:
      data_creation_in_one_statement,
      data_creation_many_statements,
      fld_creation_in_one_statement,
      fld_creation_many_statements.
ENDCLASS.


CLASS zcl_bs_demo_performance_data IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    DATA:
      ld_start TYPE timestampl,
      ld_end   TYPE timestampl.

    GET TIME STAMP FIELD ld_start.
    DO c_run_count TIMES.
      data_creation_in_one_statement( ).
    ENDDO.
    GET TIME STAMP FIELD ld_end.
    out->write( |DATA - One Statement: { ld_end - ld_start }| ).

    GET TIME STAMP FIELD ld_start.
    DO c_run_count TIMES.
      data_creation_many_statements( ).
    ENDDO.
    GET TIME STAMP FIELD ld_end.
    out->write( |DATA - Many Statements: { ld_end - ld_start }| ).

    GET TIME STAMP FIELD ld_start.
    DO c_run_count TIMES.
      fld_creation_in_one_statement( ).
    ENDDO.
    GET TIME STAMP FIELD ld_end.
    out->write( |FIELD-SYMBOL - One Statement: { ld_end - ld_start }| ).

    GET TIME STAMP FIELD ld_start.
    DO c_run_count TIMES.
      fld_creation_many_statements( ).
    ENDDO.
    GET TIME STAMP FIELD ld_end.
    out->write( |FIELD-SYMBOL - Many Statements: { ld_end - ld_start }| ).
  ENDMETHOD.


  METHOD data_creation_in_one_statement.
    DATA:
      ld_text              TYPE td_simple_text,
      ld_stream            TYPE xstring,
      ld_comment           TYPE string,
      ld_value             TYPE i,
      ld_currency          TYPE td_simple_number,
      lt_flat_standard     TYPE tt_flat_standard,
      lt_flat_sorted       TYPE tt_flat_sorted,
      lt_key_standard      TYPE tt_key_standard,
      lt_key_sorted        TYPE tt_key_sorted,
      lt_deep_standard     TYPE tt_deep_standard,
      lt_deep_sorted       TYPE tt_deep_sorted,
      lt_too_deep_standard TYPE tt_too_deep_standard,
      lt_too_deep_sorted   TYPE tt_too_deep_sorted.
  ENDMETHOD.


  METHOD data_creation_many_statements.
    DATA ld_text              TYPE td_simple_text.
    DATA ld_stream            TYPE xstring.
    DATA ld_comment           TYPE string.
    DATA ld_value             TYPE i.
    DATA ld_currency          TYPE td_simple_number.
    DATA lt_flat_standard     TYPE tt_flat_standard.
    DATA lt_flat_sorted       TYPE tt_flat_sorted.
    DATA lt_key_standard      TYPE tt_key_standard.
    DATA lt_key_sorted        TYPE tt_key_sorted.
    DATA lt_deep_standard     TYPE tt_deep_standard.
    DATA lt_deep_sorted       TYPE tt_deep_sorted.
    DATA lt_too_deep_standard TYPE tt_too_deep_standard.
    DATA lt_too_deep_sorted   TYPE tt_too_deep_sorted.
  ENDMETHOD.


  METHOD fld_creation_in_one_statement.
    FIELD-SYMBOLS:
      <ld_text>              TYPE td_simple_text,
      <ld_stream>            TYPE xstring,
      <ld_comment>           TYPE string,
      <ld_value>             TYPE i,
      <ld_currency>          TYPE td_simple_number,
      <lt_flat_standard>     TYPE tt_flat_standard,
      <lt_flat_sorted>       TYPE tt_flat_sorted,
      <lt_key_standard>      TYPE tt_key_standard,
      <lt_key_sorted>        TYPE tt_key_sorted,
      <lt_deep_standard>     TYPE tt_deep_standard,
      <lt_deep_sorted>       TYPE tt_deep_sorted,
      <lt_too_deep_standard> TYPE tt_too_deep_standard,
      <lt_too_deep_sorted>   TYPE tt_too_deep_sorted.
  ENDMETHOD.


  METHOD fld_creation_many_statements.
    FIELD-SYMBOLS <ld_text>              TYPE td_simple_text.
    FIELD-SYMBOLS <ld_stream>            TYPE xstring.
    FIELD-SYMBOLS <ld_comment>           TYPE string.
    FIELD-SYMBOLS <ld_value>             TYPE i.
    FIELD-SYMBOLS <ld_currency>          TYPE td_simple_number.
    FIELD-SYMBOLS <lt_flat_standard>     TYPE tt_flat_standard.
    FIELD-SYMBOLS <lt_flat_sorted>       TYPE tt_flat_sorted.
    FIELD-SYMBOLS <lt_key_standard>      TYPE tt_key_standard.
    FIELD-SYMBOLS <lt_key_sorted>        TYPE tt_key_sorted.
    FIELD-SYMBOLS <lt_deep_standard>     TYPE tt_deep_standard.
    FIELD-SYMBOLS <lt_deep_sorted>       TYPE tt_deep_sorted.
    FIELD-SYMBOLS <lt_too_deep_standard> TYPE tt_too_deep_standard.
    FIELD-SYMBOLS <lt_too_deep_sorted>   TYPE tt_too_deep_sorted.
  ENDMETHOD.
ENDCLASS.

 

Conclusion

As you can see from the measurement, the impact on performance seems to be so small that you can continue to choose your favorite. It doesn't matter whether it's a chain set or a single statement, the performance should always be right. For some steps, however, you can decide whether to use field symbols or references. These are particularly worthwhile in loops, although they are mostly used in inline declarations.

 

Source:
SAP Documentation - Chained statement


Included topics:
QuickChained statementDATAFIELD-SYMBOL
Comments (1)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


ABAP in Practice - Test Driven Development

Category - ABAP

How does TDD actually work in practice and are there simple examples for learning in ABAP? In this exercise we will look at the practical part.

09/24/2024

ABAP in Practice - Merge data sets

Category - ABAP

How do we merge two different data sets in ABAP, especially with regard to Modern ABAP? A practical task for this topic.

09/17/2024

ABAP in Practice - Modern ABAP

Category - ABAP

In this small task we look at existing classic ABAP source code and try to optimize it according to Modern ABAP.

08/27/2024

ABAP Quick - Performance Data Filtering

Category - ABAP

Which statement do you use in ABAP to filter internal tables and is it performant? Read more in this article.

08/13/2024

ABAP in Practice - Type Conversion

Category - ABAP

How would you perform this type conversion in ABAP? A practical example and a suggested solution.

07/16/2024