This commit is contained in:
danrega
2024-12-12 16:39:22 +01:00
parent 8c42134f33
commit 1d42f89e02
2 changed files with 351 additions and 5 deletions

View File

@@ -23,7 +23,9 @@
- [Structures in Statements for Processing Internal Tables](#structures-in-statements-for-processing-internal-tables)
- [Including Structures](#including-structures)
- [Getting Structured Type Information and Creating Structures at Runtime](#getting-structured-type-information-and-creating-structures-at-runtime)
- [sy Structure](#sy-structure)
- [Excursions](#excursions)
- [sy Structure](#sy-structure)
- [Boxed Components](#boxed-components)
- [Executable Example](#executable-example)
## Introduction
@@ -1005,8 +1007,9 @@ ENDLOOP.
<p align="right"><a href="#top">⬆️ back to top</a></p>
## Excursions
## sy Structure
### sy Structure
- The `sy` (or `syst`) structure is a built-in data object.
- The components of the structure represent ABAP system fields.
@@ -1279,6 +1282,207 @@ CLASS zcl_some_class IMPLEMENTATION.
ENDCLASS.
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
### Boxed Components
- In structures, boxed components represent nested structures managed by an internal reference.
- Currently, static boxes are supported as boxed components, enabling [initial value sharing](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENINITIAL_VALUE_SHARING_GLOSRY.html). Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENSTATIC_BOXES.html).
- The relevant addition in a structured type declaration is `BOXED`. Syntax example:
```abap
TYPES: BEGIN OF struct,
text TYPE c LENGTH 20,
nested_struct TYPE zdemo_abap_carr BOXED,
END OF struct.
```
- When used:
- Optimize memory consumption for structures used repeatedly, such as in internal tables with nested structures. Without boxed components, memory increases line by line, even if the nested structure is initial. With boxed components, memory does not increase when nested structures are initial, and only reads are performed.
- Enhance runtime performance since assignments for components with active initial value sharing require only the internal reference, not additional data to be copied.
- Boxed components allocate memory when there is write access to at least one component or when a field symbol is assigned or data reference points to at least one component.
Expand the following collapsible section for more information and example code.
<details>
<summary>🟢 Click to expand for more information and example code</summary>
<!-- -->
The following example illustrates boxed components:
- Two internal tables are created. One includes a nested structure as a boxed component, and the other includes a nested structure that is not a boxed component.
- The tables are populated in a loop under various conditions.
- The example demonstrates the impact of boxed components on memory usage.
- To try it out, proceed as follows:
- Create a demo class named `zcl_some_class`, paste the code into it, and activate it.
- The example does not display output in the console.
- It includes sections you can comment in and out. See notes in the examples.
- The code sections compare the memory usage of boxed and non-boxed components:
- *Comparison 1*: Empty nested boxed vs. empty nested non-boxed components
- *Comparison 2*: All nested boxed vs. all nested non-boxed components populated
- *Comparison 3*: Few nested boxed vs. few nested non-boxed components populated
- For the comparison:
- In ADT, add the *ABAP Memory (Debugger)* view. If not yet available, choose *Window* from the menu -> *Show View* -> *Other ...* -> filter for "memory" and add *ABAP Memory (Debugger)*.
- Set a break-point at the `ASSERT` statement.
- For *Comparison 1*, the first section is commented in. Run the class with *F9* in ADT. The first section deals with an internal table containing boxed components, where all are empty.
- The debugger stops at the break-point. Open the *ABAP Memory (Debugger)* view.
- Press *Refresh* in the view's top right corner. Check the *ABAP Application* values for used and allocated memory.
- You may want to take a screenshot for comparison.
- Stop debugging.
- Comment out the first section and comment in the next one. Ensure no other sections within the loop are commented in. This section handles an internal table with nested, non-boxed components.
- Repeat the process by setting the break-point and refreshing the view to compare memory values in the *ABAP Memory (Debugger)* view.
- Compare the resulting values of the memory consumption.
- Repeat the steps for *Comparison 2* and *Comparison 3*.
- The following observations should be made regarding the memory consumption values, reflecting the impact of boxed components:
- *Comparison 1*: Empty nested boxed vs. empty nested non-boxed components
- The table with boxed components allocates significantly less memory than the one without. Non-boxed components have full memory allocation despite having no entries.
- *Comparison 2*: All nested boxed vs. all nested non-boxed components populated
- Memory for the table with boxed components is slightly higher due to extra administrative costs.
- *Comparison 3*: Few nested boxed vs. few nested non-boxed components populated
- Large tables with boxed components show considerably less memory usage when only a few components are populated compared to tables without boxed components.
<br>
```abap
CLASS zcl_some_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_some_class IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
"Creating two demo internal tables
"One with boxed components, the other with a nested, non-boxed components
TYPES:
BEGIN OF struc,
comp1 TYPE c LENGTH 1024,
comp2 TYPE c LENGTH 1024,
END OF struc,
BEGIN OF struc_w_boxed,
id TYPE i,
boxed_comp TYPE struc BOXED,
END OF struc_w_boxed,
BEGIN OF struc_no_boxed,
id TYPE i,
struc TYPE struc,
END OF struc_no_boxed,
tab_w_boxed TYPE TABLE OF struc_w_boxed WITH EMPTY KEY,
tab_no_boxed TYPE TABLE OF struc_no_boxed WITH EMPTY KEY.
DATA: itab_w_boxed TYPE tab_w_boxed,
itab_no_boxed TYPE tab_no_boxed.
"Populating internal tables
"When running the example, only have one code snippet commented in, i.e.
"the snippets between the sections
"---- Comment in/out START ----
"...
"---- Comment in/out END ----
DO 100000 TIMES.
"------------------------------------------------------------------------
"----------------------------- Comparison 1 -----------------------------
"------------------------------------------------------------------------
"1) Internal table with boxed components: All boxed components empty
"---- Comment in/out START ----
INSERT INITIAL LINE INTO TABLE itab_w_boxed REFERENCE INTO DATA(wa1).
wa1->id = sy-index.
"---- Comment in/out END ----
**************************************************************************************************
"2) Internal table with non-boxed components: All nested, non-boxed components empty
"---- Comment in/out START ----
* INSERT INITIAL LINE INTO TABLE itab_no_boxed REFERENCE INTO DATA(wa2).
* wa2->id = sy-index.
"---- Comment in/out END ----
**************************************************************************************************
"------------------------------------------------------------------------
"----------------------------- Comparison 2 -----------------------------
"------------------------------------------------------------------------
"3) Internal table with boxed components: All boxed components filled
"---- Comment in/out START ----
* INSERT INITIAL LINE INTO TABLE itab_w_boxed REFERENCE INTO DATA(wa3).
* wa3->id = sy-index.
* wa3->boxed_comp-comp1 = sy-index.
* wa3->boxed_comp-comp2 = sy-index.
"---- Comment in/out END ----
**************************************************************************************************
"4) Internal table with non-boxed components: All nested, non-boxed components filled
"---- Comment in/out START ----
* INSERT INITIAL LINE INTO TABLE itab_no_boxed REFERENCE INTO DATA(wa4).
* wa4->id = sy-index.
* wa4->struc-comp1 = sy-index.
* wa4->struc-comp2 = sy-index.
"---- Comment in/out END ----
**************************************************************************************************
"------------------------------------------------------------------------
"----------------------------- Comparison 3 -----------------------------
"------------------------------------------------------------------------
"5) Internal table with boxed components: Only few boxed components filled
"---- Comment in/out START ----
* INSERT INITIAL LINE INTO TABLE itab_w_boxed REFERENCE INTO DATA(wa5).
* wa5->id = sy-index.
* IF sy-index <= 50.
* wa5->boxed_comp-comp1 = sy-index.
* wa5->boxed_comp-comp2 = sy-index.
* ENDIF.
"---- Comment in/out END ----
**************************************************************************************************
"6) Internal table with non-boxed components: Only few nested, non-boxed components filled
"---- Comment in/out START ----
* INSERT INITIAL LINE INTO TABLE itab_no_boxed REFERENCE INTO DATA(wa6).
* wa6->id = sy-index.
* IF sy-index <= 50.
* wa6->struc-comp1 = sy-index.
* wa6->struc-comp2 = sy-index.
* ENDIF.
"---- Comment in/out END ----
ENDDO.
ASSERT 1 = 1.
ENDMETHOD.
ENDCLASS.
```
</details>
<p align="right"><a href="#top">⬆️ back to top</a></p>

View File

@@ -43,7 +43,9 @@
- [Excursions](#excursions)
- [Comparison Operators for Character-Like Data Types in a Nutshell](#comparison-operators-for-character-like-data-types-in-a-nutshell)
- [Classes for String Processing](#classes-for-string-processing)
- [Character String and Byte String Processing with ABAP Statements](#character-string-and-byte-string-processing-with-abap-statements)
- [Byte String Processing](#byte-string-processing)
- [Character String and Byte String Processing with ABAP Statements](#character-string-and-byte-string-processing-with-abap-statements)
- [SET BIT and GET BIT Statements](#set-bit-and-get-bit-statements)
- [Executable Example](#executable-example)
@@ -2244,7 +2246,9 @@ As also covered in the [Released ABAP Classes](22_Released_ABAP_Classes.md) chea
<p align="right"><a href="#top">⬆️ back to top</a></p>
### Character String and Byte String Processing with ABAP Statements
### Byte String Processing
#### Character String and Byte String Processing with ABAP Statements
- Several ABAP statements include the `IN CHARACTER MODE` and `IN BYTE MODE` additions.
- These additions determine whether operations process character strings or byte strings.
@@ -2252,7 +2256,6 @@ As also covered in the [Released ABAP Classes](22_Released_ABAP_Classes.md) chea
- Byte string processing with the `IN BYTE MODE` addition is supported by the following ABAP statements: `CONCATENATE`, `FIND`, `REPLACE`, `SHIFT`, `SPLIT`.
- In byte string processing, the data objects used must be byte-like. For character string processing, only character-like data objects are allowed.
The following code snippet explores various statements with the `IN CHARACTER MODE` and `IN BYTE MODE` additions.
```abap
@@ -2407,6 +2410,145 @@ SPLIT xstr AT blank_xstr INTO DATA(xstr1) DATA(xstr2) IN BYTE MODE.
SPLIT xstr AT blank_xstr INTO TABLE DATA(xstr_tab) IN BYTE MODE.
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
#### SET BIT and GET BIT Statements
- Unlike the ABAP statements in the previous section, the following statements are are only for byte string processing:
- [`SET BIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABAPSET_BIT.html) and .
- Syntax pattern: `SET BIT pos OF byte_string [TO value].`
- In a byte-like data object, the bit is set to 1 by default at a specified position, or to 0 or 1 as specified after `TO`.
- Alternatively, you can use the built-in function [`bit-set`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENBIT_FUNCTIONS.html).
- [`GET BIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABAPGET_BIT.html)
- Syntax pattern: `GET BIT pos OF byte_string INTO value.`
- Reads a bit at a specified position in a byte string into a target data object.
Expand the following collapsible section for example code, which experiments with byte string processing (converting a hexadecimal value to the character-like representation of the binary values by reading bits, getting hexadecimal values from from the character-like representation of the binary values, setting bits). To try it out, create a demo class named `zcl_some_class` and paste the code into it. After activation, choose *F9* in ADT to execute the class. The example is set up to display output in the console.
<details>
<summary>🟢 Click to expand for example code</summary>
<!-- -->
```abap
CLASS zcl_some_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_some_class IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
"Converting an example text string to xstring
"The conversion is performed using the default code page UTF-8.
"48656C6C6F2041424150
DATA(demo_string) = `Hello ABAP`.
DATA(xstr) = cl_abap_conv_codepage=>create_out( )->convert( demo_string ).
TYPES: BEGIN OF struc,
bin TYPE string,
hex_value TYPE xstring,
END OF struc.
DATA tab TYPE TABLE OF struc WITH EMPTY KEY.
"Determining the length of the hexadecimal value 48656C6C6F2041424150
"and multiplying by 8 for reading the bits
DATA(length_xstr) = xstrlen( xstr ) * 8.
"Data object to store the binary representation of hexadecimal values
DATA binary_rep TYPE string.
"Reading the bits from front to back
"The example is implemented in a way to perform a byte-wise storing
"of the binary representations of hexadecimal values in an internal table
"to visualize individual bytes. After 8 bits, the next byte is processed.
WHILE sy-index <= length_xstr.
GET BIT sy-index OF xstr INTO DATA(bit).
binary_rep &&= |{ bit }|.
IF sy-index MOD 8 = 0.
APPEND VALUE #( bin = binary_rep ) TO tab.
CLEAR binary_rep.
ENDIF.
ENDWHILE.
"Getting hexadecimal values from the character-like representation of
"the binary values
LOOP AT tab REFERENCE INTO DATA(line).
DATA(num) = 0.
DO strlen( line->bin ) TIMES.
DATA(pos) = strlen( line->bin ) - sy-index.
num += COND i( WHEN line->bin+pos(1) = '1' THEN 2 ** ( sy-index - 1 ) ).
ENDDO.
line->hex_value = CONV xstring( num ).
ENDLOOP.
"Table reduction: Concatenating the individual hexadecimal values
DATA(hex_value) = REDUCE xstring( INIT xs = ``
FOR <li> IN tab
NEXT xs &&= <li>-hex_value ).
out->write( data = tab name = `tab` ).
out->write( |\n| ).
ASSERT hex_value = xstr.
out->write( data = hex_value name = `hex_value` ).
out->write( |\n| ).
"Converting xstring to string
DATA(conv_string) = cl_abap_conv_codepage=>create_in( )->convert( hex_value ).
ASSERT conv_string = demo_string.
out->write( data = conv_string name = `conv_string` ).
out->write( |\n| ).
"SET BIT
"Adding `!` to the demo string
"The binary representation of `!` corresponds to 00100001.
"The hex_val data object has eight bits. In a loop, the
"binary representation is looped across. Depending on the
"value 0 or 1, SET BIT statements set values accordingly.
"Finally, the resulting data object is assigned to the demo
"xstring, and converted to string.
DATA hex_val TYPE x LENGTH 1.
DATA(excl_mark) = `00100001`.
DATA(length_str) = strlen( excl_mark ).
DO 8 TIMES.
DATA(idx_for_position) = sy-index - 1.
DATA(value_at_position) = SWITCH #( sy-index WHEN 1 THEN excl_mark+0(1) ELSE excl_mark+idx_for_position(1) ).
CASE value_at_position.
WHEN `0`.
SET BIT sy-index OF hex_val TO 0.
WHEN `1`.
SET BIT sy-index OF hex_val.
ENDCASE.
ENDDO.
xstr = xstr && hex_val.
conv_string = cl_abap_conv_codepage=>create_in( )->convert( xstr ).
ASSERT conv_string = |{ demo_string }!|.
out->write( data = conv_string name = `conv_string` ).
ENDMETHOD.
ENDCLASS.
```
</details>
<p align="right"><a href="#top">⬆️ back to top</a></p>
## Executable Example