Go on link..

link us with ...

Monday, January 3, 2011

Measure the Performance between Break-Points using SE30

Today we will elaborate the option to measure the performance of the specific part of the code using the SE30. This option would be helpful when we want to measure the performance of particular subroutine, FM, Select query etc. We have the option to start the runtime analysis and stop it on the fly by options System > Utilities > Runtime Analysis > Switch On and Switch Off.


For demo, we will set two breakpoints: one before starting the FM and one after FM.



When we reach at the breakpoint and we try to start the performance measurement by option Utilities > Runtime Analysis > Switch On, system would give the message as "The Particular units" option is not selected.


This message appears because the DEFAULT variant doesn't have this option selected. You can see this variant in SE30. Enter the DEFAULT and press the "Display" button.


So, we need to select the option "Particular Units" in the measurement variant. To do this, we will copy this standard measurement variant to user specific variant and then select the option "Particular Units".

To measure the performance:
1) Run SE30
2) Select this newly copied variant. Here we need to select User Defined variant.

3) Enter the required program / transaction and measure it
4) When it reaches to the breakpoint ON the measurement by System > Utilities > Runtime Analysis > Switch On
5) Press F8
6) When it reaches to the next breakpoint ON the measurement by System > Utilities > Runtime Analysis > Switch Off
7) After finishing the entire transaction, press the evaluate button to evaluate the performance of required code lines.

TIP:
Runtime performance can be switched ON by enter /RON in the transaction box when it reaches to the desired breakpoint. Same way /ROFF could be used to switch off the performance measurement.

Use of Field-symbols vs Work area

To use the Field-symbols against the Work Area for Internal table processing


Internal table processing is essential part of any ABAP program. Generally, we use the explicit work area to process the internal table like appending & modifying records. We can reduce the time and improve the performance of the program by using the field-symbols.

When we use the LOOP construct with the explicit work area, system need to engage the resources to put the required record in the work area, process it and move it back to the table if the needed. This additional processing time could be saved by using the field-symbol. By using the field-symbols we can save this additional time and improve the performance. Field-symbols are similar to dereferenced pointers in C. While using the field-symbol, system uses the same memory allocated to that particular field in the record instead of moving it to work area and processing. More on field-symbols can be found at: Field-Symbols on SAP Help.

This code snippet shows how to use the field-symbols to process the loop with time measurement.
Code Snippet
  
*&---------------------------------------------------------------------*
*& Illustrate the performance gain by using the field-symbols
*& over header areas
*&---------------------------------------------------------------------*
*
REPORT ztest_np_loop_fs.
*
DATA: i_bseg TYPE STANDARD TABLE OF bseg,
wa_bseg LIKE LINE OF i_bseg.
*
DATA: lv_flag TYPE flag,
lv_sta_time TYPE timestampl,
lv_end_time TYPE timestampl,
lv_diff_w TYPE p DECIMALS 5,
lv_diff_f LIKE lv_diff_w,
lv_save LIKE lv_diff_w.
*
FIELD-SYMBOLS: LIKE LINE OF i_bseg.
*
* data selection = 10,000 records
SELECT * FROM bseg INTO TABLE i_bseg UP TO 100 ROWS.
*
* Begin - Processing with Work area
GET TIME STAMP FIELD lv_sta_time.
LOOP AT i_bseg INTO wa_bseg.
IF lv_flag = 'X'.
wa_bseg-sgtxt = 'TEST'.
MODIFY i_bseg FROM wa_bseg.
ENDIF.
CLEAR wa_bseg.
IF lv_flag IS INITIAL.
lv_flag = 'X'.
ENDIF.
ENDLOOP.
GET TIME STAMP FIELD lv_end_time.
lv_diff_w = lv_end_time - lv_sta_time.
WRITE: /(15) 'Work area', lv_diff_w.
* End - Processing with Work Area
*
CLEAR: lv_flag,
lv_sta_time,
lv_end_time.
* Begin - Processing with Field-Symbols
GET TIME STAMP FIELD lv_sta_time.
LOOP AT i_bseg ASSIGNING .
IF lv_flag = 'X'.
-sgtxt = 'TEST'.
ENDIF.
IF lv_flag IS INITIAL.
lv_flag = 'X'.
ENDIF.
ENDLOOP.
GET TIME STAMP FIELD lv_end_time.
lv_diff_f = lv_end_time - lv_sta_time.
WRITE: /(15) 'Field-Symbol', lv_diff_f.
* End - Processing with Work Area
*
* Net time saving
lv_save = lv_diff_w - lv_diff_f.
WRITE: /(15) 'Total Save', lv_save.
WRITE: / 'Done'.



Some statistics:
In this performance measurement, time taken by the work area to process is considered as the 100%. By using the field-symbols, we can definitely improve the performance.





Parallel Cursor - 2: without using READ

Parallel Cursor without using READ


In previous post Parallel Cursor - To speed up performance of Nested LOOP, we have seen a technique how to speed up the performance of the nested LOOP constructs in ABAP. In today's post, we will see another variance of the Parallel cursor technique. In this technique, we will exit out the inner LOOP when both keys are not matching by saving the LOOP index in a variable. This index variable would be used in the LOOP construct to start the LOOP. Initially, this index variable would be set to 1. Statistics shows that this new technique is powerful over the technique as shown in the previous post which uses the READ TABLE.

Here is the code snippet to achieve this Parallel Cursor technique:
Code Snippet
  
*&---------------------------------------------------------------------*
*& Report ZTEST_NP_PARALLEL_CURSOR
*& Purpose: Illustration on how to use Parallel Cursor
*&---------------------------------------------------------------------*
*
REPORT ztest_np_parallel_cursor.
*
TYPES: ty_t_vbak TYPE STANDARD TABLE OF vbak.
DATA: it_vbak TYPE ty_t_vbak .
*
TYPES: ty_t_vbap TYPE STANDARD TABLE OF vbap.
DATA: it_vbap TYPE ty_t_vbap.
*
FIELD-SYMBOLS: LIKE LINE OF it_vbak,
LIKE LINE OF it_vbap.
*
* necessary data selection
SELECT * FROM vbak
INTO TABLE it_vbak
UP TO 100 ROWS.
CHECK it_vbak IS NOT INITIAL.
SELECT * FROM vbap
INTO TABLE it_vbap
FOR ALL ENTRIES IN it_vbak
WHERE vbeln = it_vbak-vbeln.
*
DATA: lv_start_time TYPE timestampl,
lv_end_time TYPE timestampl,
lv_diff TYPE timestampl.
DATA: lv_tabix TYPE i.
*
*....... Parallel Cursor with Nested Loop .......................
* Get the Start Time
GET TIME STAMP FIELD lv_start_time.
*
* Starting the Parallel Cursor
SORT: it_vbak BY vbeln,
it_vbap BY vbeln.
LOOP AT it_vbak ASSIGNING .
*
* Read the second internal table with BINARY SEARCH
READ TABLE it_vbap TRANSPORTING NO FIELDS
WITH KEY vbeln = -vbeln
BINARY SEARCH.
* Get the TABIX number
lv_tabix = sy-tabix.
* Start the LOOP from the first accessed record in
* previous READ i.e. LV_TABIX
LOOP AT it_vbap FROM lv_tabix ASSIGNING .
*
* End the LOOP, when there is no more record with similar key
IF -vbeln <> -vbeln.
EXIT.
ENDIF.
* Rest of the logic would go from here...
*
ENDLOOP.
*
ENDLOOP.
*
* Get the end time
GET TIME STAMP FIELD lv_end_time.
*
* Actual time Spent:
lv_diff = lv_end_time - lv_start_time.
WRITE: /(50) 'Time Spent on Parallel Cursor Nested loops:', lv_diff.
CLEAR: lv_start_time, lv_end_time, lv_diff.
*
*....... Parallel Cursor - 2 with Nested Loop ...................
Clear lv_tabix.
* Get the Start Time
GET TIME STAMP FIELD lv_start_time.
*
* Starting the Parallel Cursor
SORT: it_vbak BY vbeln,
it_vbap BY vbeln.
lv_tabix = 1. " Set the starting index 1
LOOP AT it_vbak ASSIGNING .
*
* Start the nested LOOP from the index
LOOP AT it_vbap from lv_tabix
ASSIGNING .
* Save index & Exit the loop, if the keys are not same
if -vbeln <> -vbeln.
lv_tabix = sy-tabix.
EXIT.
ENDIF.
* Rest of the logic would go from here...
*
ENDLOOP.
ENDLOOP.
*
* Get the end time
GET TIME STAMP FIELD lv_end_time.
*
* Actual time Spent:
lv_diff = lv_end_time - lv_start_time.
WRITE: /(50) 'Time Spent on Parallel Cursor 2 Nested loops', lv_diff.
CLEAR: lv_start_time, lv_end_time, lv_diff.



This statistics and graph shows the time used by the nested LOOP as the 100%. For the 1000 VBAK records, parallel cursor technique with READ consumes 1.84% time compare to nested LOOPs 100%. This technique without READ TABLE only requires 1.05% time compare to 100% of nested LOOPs.





Parallel Cursor - To speed up performance of Nested LOOP

Technique to speed up the performance of the Nested LOOP - Parllel Cursor


I'm back after a long break. Today, we will tackle down the biggest performance related issue around the Nested Loops.

Traditionally in ABAP, we use the LOOP using the WHERE clause for Nested loops. This type of nested loops are very common in our day-to-day programming. But, the cost, in terms of performance, is higher when we use the nested loops. This cost would become a key issue when working with huge tables e.g. BKPF & BSEG, VBAK & VBAP, MKPF & MSEG. Sometimes, this cost increases and reaches to the point where program fails to finish the execution.

We have the concept of Parallel Cursor exists in ABAP to overcome this hurdle and reduce this cost. In parallel cursor, we first try to see if there is any entry exist in the second table inside the LOOP construct of first table. We use the READ .. WITH KEY .. BINARY SEARCH to check if the entry exist in the second table. We use this record number SY-TABIX to LOOP on the second table using LOOP .. FROM index.

This code snippet gives us the idea of the time taken by both the nested loops and the parallel cursor loops.
Code Snippet
  
*&---------------------------------------------------------------------*
*& Report ZTEST_NP_PARALLEL_CURSOR
*& Purpose: Illustration on how to use Parallel Cursor
*&---------------------------------------------------------------------*
*
REPORT ztest_np_parallel_cursor.
*
TYPES: ty_t_vbak TYPE STANDARD TABLE OF vbak.
DATA: it_vbak TYPE ty_t_vbak .
*
TYPES: ty_t_vbap TYPE STANDARD TABLE OF vbap.
DATA: it_vbap TYPE ty_t_vbap.
*
FIELD-SYMBOLS: LIKE LINE OF it_vbak,
LIKE LINE OF it_vbap.
*
* necessary data selection
SELECT * FROM vbak
INTO TABLE it_vbak
UP TO 1000 ROWS.
CHECK it_vbak IS NOT INITIAL.
SELECT * FROM vbap
INTO TABLE it_vbap
FOR ALL ENTRIES IN it_vbak
WHERE vbeln = it_vbak-vbeln.
*
DATA: lv_start_time TYPE timestampl,
lv_end_time TYPE timestampl,
lv_diff TYPE timestampl.
DATA: lv_tabix TYPE i.
*
*...... Normal Nested Loop .................................
* Get the Start Time
GET TIME STAMP FIELD lv_start_time.
*
* Nested Loop
LOOP AT it_vbak ASSIGNING .
LOOP AT it_vbap ASSIGNING
WHERE vbeln = -vbeln.
ENDLOOP.
ENDLOOP.
*
* Get the end time
GET TIME STAMP FIELD lv_end_time.
*
* Actual time Spent:
lv_diff = lv_end_time - lv_start_time.
WRITE: /(50) 'Time Spent on Nested Loop', lv_diff.
*
CLEAR: lv_start_time, lv_end_time, lv_diff.
*
*....... Parallel Cursor with Nested Loop .......................
* Get the Start Time
GET TIME STAMP FIELD lv_start_time.
*
* Starting the Parallel Cursor
SORT: it_vbak BY vbeln,
it_vbap BY vbeln.
LOOP AT it_vbak ASSIGNING .
*
* Read the second internal table with BINARY SEARCH
READ TABLE it_vbap TRANSPORTING NO FIELDS
WITH KEY vbeln = -vbeln
BINARY SEARCH.
* Get the TABIX number
lv_tabix = sy-tabix.
* Start the LOOP from the first accessed record in
* previous READ i.e. LV_TABIX
LOOP AT it_vbap FROM lv_tabix ASSIGNING .
*
* End the LOOP, when there is no more record with similar key
IF -vbeln <> -vbeln.
EXIT.
ENDIF.
* Rest of the logic would go from here...
*
ENDLOOP.
*
ENDLOOP.
*
* Get the end time
GET TIME STAMP FIELD lv_end_time.
*
* Actual time Spent:
lv_diff = lv_end_time - lv_start_time.
WRITE: /(50) 'Time Specnt on Parallel Cursor Nested loops:', lv_diff.


I ran this program multiple times and capture this statistics.

No comments:

link us...

For Visitors

if you want to publish or Add something on ERP, SAP , SAP FUNCTIONAL, SAP ABAP then mail us along with your email-id. contain must be yours

email-id :- avinashkr_raj@yahoo.com(any email)

email-id :- avinaskr_raj.abap@blogger.com ( use only gmail)