본문 바로가기
ABAP/개발Tip

[개발Tip] APPEND 성능 비교 (value for, loop, move 등)

by name_text 2024. 10. 24.

APPEND 성능 비교 (value for, loop, move 등)

VALUE FOR, LOOP APPEND, MOVE

 

Internal Table의 일부 필드값을 Range로 만들 경우 편리함 때문에 요즘에는 계속 value for만 사용하고 있었는데,

문득 동일한 데이터를 Append 할때 loop append가 빠른지 value for가 빠른지 궁금하여 실험을 해봤습니다.

 

나름대로 여러가지를 테스트 해봤는데. 어마어마한 차이는 없는듯 합니다.

 

그나마 단순히 A itab을 B itab으로 복사할 경우 move-corresponding이 압도적으로 빠르고

조건에 따라 필터링해서 데이터를 복사할 경우 value for assigning이 조금이라도 더 빨랐습니다.

 

그리고, 모든 경우에서 into 보다 assigning이 조금이라도 더 빠릅니다.

아무래도 Internal Table의 특정 레코드의 데이터를 wa로 복사하는 into 보다는 주소값만 가지고 있는 assigning이 성능 면에서는 더 효과적인 듯 합니다.

 

# 소스코드

REPORT yappend_who_is_best LINE-SIZE 500.

TYPES: BEGIN OF ts_result,
         step       TYPE i,
         category   TYPE string,
         text       TYPE string,
         rtime      TYPE i,
         rtime_unit TYPE string,
       END OF ts_result,
       tt_result TYPE STANDARD TABLE OF ts_result WITH EMPTY KEY.

DATA: lt_temp TYPE STANDARD TABLE OF dd03l,
      ls_temp LIKE LINE OF lt_temp.
DATA: lt_itab  TYPE RANGE OF dd03l-fieldname,
      ls_itab  LIKE LINE OF lt_itab,
      lt_itab2 TYPE STANDARD TABLE OF dd03l.

DATA: lv_rtime  TYPE i,
      lt_result TYPE tt_result.

PARAMETERS p_count TYPE i OBLIGATORY DEFAULT 1000000.

START-OF-SELECTION.

  FREE : lt_itab, lt_temp, lt_result.

  SELECT
    fieldname
  FROM dd03l
    UP TO @p_count ROWS
  INTO CORRESPONDING FIELDS OF TABLE @lt_temp.
*  DO p_count TIMES.
*    CALL FUNCTION 'GENERAL_GET_RANDOM_STRING'
*      EXPORTING
*        number_chars  = 5
*      IMPORTING
*        random_string = lv_string.
*    MOVE: lv_string TO ls_temp-key1. CONDENSE ls_temp-key1.
*    ls_temp-key1 = ls_temp-key1 && sy-tabix.
*    APPEND ls_temp TO lt_temp.
*  ENDDO.

  "Directly appending

  "VALUE FOR
  FREE lt_itab2.
  GET RUN TIME FIELD lv_rtime.
  lt_itab2 = VALUE #( FOR ls1 IN lt_temp
                     ( ls1 ) ).
  PERFORM determine_write USING 'Directly Appending' 'VALUE FOR - INTO'
                                lv_rtime.

  FREE lt_itab2.
  GET RUN TIME FIELD lv_rtime.
  lt_itab2 = VALUE #( FOR <lfs1> IN lt_temp
                     ( <lfs1> ) ).
  PERFORM determine_write USING 'Directly Appending' 'VALUE FOR - ASSIGNING'
                                lv_rtime.

  "LOOP
  FREE lt_itab2.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp INTO DATA(ls_temp1).
    APPEND ls_temp1 TO lt_itab2.
  ENDLOOP.
  PERFORM determine_write USING 'Directly Appending' 'LOOP - INTO'
                                lv_rtime.

  FREE lt_itab2.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp ASSIGNING FIELD-SYMBOL(<lfs_temp>).
    APPEND <lfs_temp> TO lt_itab2.
  ENDLOOP.
  PERFORM determine_write USING 'Directly Appending' 'LOOP - ASSIGNING'
                                lv_rtime.

  "CORRESPONDING
  FREE lt_itab2.
  GET RUN TIME FIELD lv_rtime.
  lt_itab2 = CORRESPONDING #( lt_temp ).
  PERFORM determine_write USING 'Directly Appending' 'CORRESPONDING'
                                lv_rtime.

  "MOVE-CORRESPONDING
*  FREE lt_itab2.
  GET RUN TIME FIELD lv_rtime.
  CLEAR lt_itab2.
  MOVE-CORRESPONDING lt_temp TO lt_itab2.
  PERFORM determine_write USING 'Directly Appending' 'MOVE-CORRESPONDING'
                                lv_rtime.

  "VALUE FOR
  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  lt_itab = VALUE #( FOR ls2 IN lt_temp
                     ( sign   = 'I'
                       option = 'EQ'
                       low    = ls2-fieldname ) ).
  PERFORM determine_write USING 'APPEND VALUE #' 'VALUE FOR - INTO'
                                lv_rtime.

  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  lt_itab = VALUE #( FOR <lfs2> IN lt_temp
                     ( sign   = 'I'
                       option = 'EQ'
                       low    = <lfs2>-fieldname ) ).
  PERFORM determine_write USING 'APPEND VALUE #' 'VALUE FOR - ASSIGNING'
                                lv_rtime.

  "LOOP VALUE
  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp INTO DATA(ls_temp2).
    APPEND VALUE #( sign   = 'I'
                    option = 'EQ'
                    low    = ls_temp2-fieldname ) TO lt_itab.
  ENDLOOP.
  PERFORM determine_write USING 'APPEND VALUE #' 'LOOP VALUE with INTO'
                                lv_rtime.

  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp ASSIGNING FIELD-SYMBOL(<lfs_temp1>).
    APPEND VALUE #( sign   = 'I'
                    option = 'EQ'
                    low    = <lfs_temp1>-fieldname ) TO lt_itab.
  ENDLOOP.
  PERFORM determine_write USING 'APPEND VALUE #' 'LOOP VALUE with ASSIGNING'
                                lv_rtime.

  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp REFERENCE INTO DATA(ld_temp1).
    APPEND VALUE #( sign   = 'I'
                    option = 'EQ'
                    low    = ld_temp1->fieldname ) TO lt_itab.
  ENDLOOP.
  PERFORM determine_write USING 'APPEND VALUE #' 'LOOP VALUE with REFERENCE'
                                lv_rtime.


  "VALUE FOR CORRESPONDING
  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  lt_itab = VALUE #( FOR ls3 IN lt_temp
                     ( VALUE #( BASE CORRESPONDING #( ls3
                                                      MAPPING low = fieldname )
                                sign   = 'I'
                                option = 'EQ' ) ) ).
  PERFORM determine_write USING 'APPEND CORRESPONDING #' 'VALUE FOR CORRESPONDING'
                                lv_rtime.

  "LOOP CORRESPONDING
  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp ASSIGNING FIELD-SYMBOL(<lfs_temp2>).
    ls_itab = CORRESPONDING #( <lfs_temp2>
                               MAPPING low = fieldname ).
    ls_itab-sign = 'I'.
    ls_itab-option = 'EQ'.
    APPEND ls_itab TO lt_itab.
  ENDLOOP.
  PERFORM determine_write USING 'APPEND CORRESPONDING #' 'LOOP CORRESPONDING'
                                lv_rtime.

  "CORRESPONDING
  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  lt_itab = CORRESPONDING #( lt_temp
                             MAPPING low = fieldname ).
  READ TABLE lt_itab INTO ls_itab INDEX 1.
  ls_itab-sign    = 'I'.
  ls_itab-option  = 'EQ'.
  MODIFY lt_itab FROM ls_itab TRANSPORTING sign option WHERE sign IS INITIAL.
  PERFORM determine_write USING 'APPEND CORRESPONDING #' 'CORRESPONDING & MODIFY'
                                lv_rtime.


  "LOOP Using WA
  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp INTO ls_temp.
    ls_itab-sign = 'I'.
    ls_itab-option = 'EQ'.
    ls_itab-low = ls_temp-fieldname.
    APPEND ls_itab TO lt_itab.
  ENDLOOP.
  PERFORM determine_write USING 'LOOP 처리 방식 차이' 'LOOP Using WA'
                                lv_rtime.

  "LOOP Using WA & Clear wa
  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp INTO ls_temp.
    ls_itab-sign = 'I'.
    ls_itab-option = 'EQ'.
    ls_itab-low = ls_temp-fieldname.
    APPEND ls_itab TO lt_itab.
    CLEAR ls_itab.
  ENDLOOP.
  PERFORM determine_write USING 'LOOP 처리 방식 차이' 'LOOP Using WA & Clear wa'
                                lv_rtime.

  "LOOP LOOP MOVE-CORRESPONDING
  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp INTO ls_temp.
    MOVE-CORRESPONDING ls_temp TO ls_itab.
    ls_itab-sign = 'I'.
    ls_itab-option = 'EQ'.
    ls_itab-low = ls_temp-fieldname.
    APPEND ls_itab TO lt_itab.
    CLEAR ls_itab.
  ENDLOOP.
  PERFORM determine_write USING 'LOOP 처리 방식 차이' 'LOOP MOVE-CORRESPONDING'
                                lv_rtime.

  "LOOP
  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp INTO DATA(ls_temp9).
    ls_itab-sign = 'I'.
    ls_itab-option = 'EQ'.
    ls_itab-low = ls_temp2-fieldname.
    APPEND ls_itab TO lt_itab.
  ENDLOOP.
  PERFORM determine_write USING 'LOOP 처리 방식 차이' 'LOOP INTO DATA'
                                lv_rtime.

  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp ASSIGNING FIELD-SYMBOL(<lfs_temp9>).
    ls_itab-sign = 'I'.
    ls_itab-option = 'EQ'.
    ls_itab-low = <lfs_temp9>-fieldname.
    APPEND ls_itab TO lt_itab.
  ENDLOOP.
  PERFORM determine_write USING 'LOOP 처리 방식 차이' 'LOOP ASSIGNING'
                                lv_rtime.

  FREE lt_itab.
  GET RUN TIME FIELD lv_rtime.
  LOOP AT lt_temp REFERENCE INTO DATA(ld_temp9).
    ls_itab-sign = 'I'.
    ls_itab-option = 'EQ'.
    ls_itab-low = ld_temp9->fieldname.
    APPEND ls_itab TO lt_itab.
  ENDLOOP.
  PERFORM determine_write USING 'LOOP 처리 방식 차이' 'LOOP REFERENCE'
                                lv_rtime.


  "Result
  ycl_salv_output=>display( lt_result ).


*&---------------------------------------------------------------------*
*& Form DETERMINE_WRITE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> P_
*&      --> LV_SDATE
*&      --> LV_STIME
*&---------------------------------------------------------------------*
FORM determine_write  USING    pv_category
                               pv_text
                               pv_rtime.
  DATA: lv_rtime TYPE i,
        lv_ftime TYPE i.
  GET RUN TIME FIELD lv_rtime.
  lv_ftime = lv_rtime - pv_rtime.

  APPEND VALUE #( step        = lines( lt_result ) + 1
                  category    = pv_category
                  text        = pv_text
                  rtime       = lv_ftime
                  rtime_unit  = MicroSecond ) TO lt_result.
*  WRITE :/ pv_text,
*           30 ' : ', lv_ftime, 'MicroSecond'.
ENDFORM.

댓글