SAP 提供多种多线程的方法去优化程序的执行效率
1.分别执行多个job
2.Call function STARTING NEW TASK
3.直接使用SAP 提供的SPTA 框架函数:SPTA_PARA_PROCESS_START_2
本次,我们着重来介绍一下三种方法中函数的使用方法
获取空闲线程数:SPBT_INITIALIZE
*&---------------------------------------------------------------------*
*& Report  ZDEMO_TEST_PARALLEL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*REPORT  zdemo_test_parallel.
TYPE-POOLS:spta.
DATA: gs_head  TYPE zsfi_doc_head.
DATA: gt_head  TYPE STANDARD TABLE OF zsfi_doc_head.
DATA: gt_out   TYPE STANDARD TABLE OF zsfi_doc_head_o.
DATA: gt_item  TYPE STANDARD TABLE OF zsfi_doc_item.
DATA: gs_item  TYPE zsfi_doc_item.
DATA: ls_head  TYPE zsfi_doc_head.
DATA: lt_head  TYPE STANDARD TABLE OF zsfi_doc_head.
DATA: lt_item  TYPE STANDARD TABLE OF zsfi_doc_item.
DATA: ls_item  TYPE zsfi_doc_item.
DATA: lv_int     TYPE numc4.
DATA: gs_parallel TYPE zsfi_doc_head_run.
DATA: gt_parallel TYPE ztfi_doc_head_run_t.
DATA: gt_result TYPE ztfi_doc_head_run_t.DATA: gv_start TYPE char10.
DATA: gv_end   TYPE char10.SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME  TITLE text-t01.
PARAMETERS: p_group TYPE spta_rfcgr OBLIGATORY MEMORY ID spta_rfcgr DEFAULT 'parallel_generators'.
PARAMETERS: p_task  LIKE sy-index DEFAULT '10'.
PARAMETERS: p_times TYPE numc4 OBLIGATORY DEFAULT '100'.
PARAMETERS: p_loop  TYPE char01 RADIOBUTTON GROUP rd1 DEFAULT 'X'.
PARAMETERS: p_para  TYPE char01 RADIOBUTTON GROUP rd1 .SELECTION-SCREEN END OF BLOCK b1.START-OF-SELECTION.lv_int = p_times.SELECT SINGLE *INTO CORRESPONDING FIELDS OF ls_headFROM ztfi_doc_headWHERE zsernr = 'BPM26020240606000003'.SELECT  *INTO CORRESPONDING FIELDS OF TABLE lt_itemFROM ztfi_doc_itemWHERE zsernr = 'BPM26020240606000003'.CASE 'X'.WHEN p_loop.PERFORM frm_loop_process.WHEN p_para.PERFORM frm_parallel_process.WHEN OTHERS.ENDCASE.*&---------------------------------------------------------------------*
*&      Form  FRM_LOOP_PROCESS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_loop_process .DATA: lv_errcode TYPE char8.DATA: lv_errdesc TYPE char250.gv_start = sy-uzeit.IF  ls_head IS NOT INITIAL AND lt_item IS NOT INITIAL .DO p_times TIMES.lv_int = lv_int - 1.CLEAR:lv_errcode,lv_errdesc,gt_item,gt_head,gt_out.CONCATENATE  'BPM06020240612LOOP9' lv_int INTO ls_head-zsernr.CONCATENATE  '240606LOOP4' lv_int INTO ls_head-orderid.APPEND ls_head TO gt_head.LOOP AT  lt_item INTO ls_item .CONCATENATE 'BPM06020240612LOOP9' lv_int INTO ls_item-zsernr.APPEND ls_item TO gt_item.ENDLOOP.CALL FUNCTION 'ZFIFM_RECEIPT_POSTING'IMPORTINGerrcode = lv_errcodeerrdesc = lv_errdescTABLESit_head = gt_headit_item = gt_itemot_head = gt_out.ENDDO.ENDIF.gv_end = sy-uzeit.WRITE gv_start.WRITE gv_end.ENDFORM.                    " FRM_LOOP_PROCESS
*&---------------------------------------------------------------------*
*&      Form  FRM_PARALLEL_PROCESS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_parallel_process .CLEAR:gt_parallel.DO p_times TIMES.lv_int = lv_int + 1.CLEAR:gt_item,gt_head,gs_parallel.CONCATENATE  'BPM06020240612PARALLEL9' lv_int INTO ls_head-zsernr.CONCATENATE  '240612PARAL9' lv_int INTO ls_head-orderid.MOVE-CORRESPONDING ls_head TO gs_parallel.LOOP AT  lt_item INTO ls_item .CONCATENATE 'BPM06020240612PARALLEL9' lv_int INTO ls_item-zsernr.APPEND ls_item TO gt_item.ENDLOOP.gs_parallel-item = gt_item.APPEND gs_parallel TO  gt_parallel.ENDDO.gv_start = sy-uzeit.CALL FUNCTION 'SPTA_PARA_PROCESS_START_2'EXPORTINGserver_group             = p_groupmax_no_of_tasks          = p_taskbefore_rfc_callback_form = 'BEFORE_RFC'in_rfc_callback_form     = 'IN_RFC'after_rfc_callback_form  = 'AFTER_RFC'callback_prog            = sy-repidCHANGINGuser_param               = gt_parallel   "this is for you to transfer data you want to dealEXCEPTIONSinvalid_server_group     = 1no_resources_available   = 2OTHERS                   = 3.gv_end = sy-uzeit.WRITE gv_start.WRITE gv_end.ENDFORM.                    " FRM_PARALLEL_PROCESS*&---------------------------------------------------------------------*
*&      Form  before_rfc
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->IS_BEFORE_RFC_IMP      text
*      -->CS_BEFORE_RFC_EXP      text
*      -->CT_RFCDATA            text
*      -->CT_FAILED_OBJECTS      text
*      -->CT_OBJECTS_IN_PROCESS  text
*      -->P_USER_PARAM          text
*----------------------------------------------------------------------*
FORM before_rfc    USING  is_before_rfc_imp     TYPE spta_t_before_rfc_impCHANGINGcs_before_rfc_exp      TYPE spta_t_before_rfc_expct_rfcdata             TYPE spta_t_indxtabct_failed_objects      TYPE spta_t_failed_objectsct_objects_in_process  TYPE spta_t_objects_in_processct_user_param          TYPE ztfi_doc_head_run_t.   " you own dataDATA: ls_parallel TYPE zsfi_doc_head_run.DATA: lt_parallel TYPE STANDARD TABLE OF  zsfi_doc_head_run.DATA: lv_counter TYPE i.DATA: lv_package TYPE i.* define the package size as 10lv_package = 10.CLEAR:lt_parallel.LOOP AT ct_user_param INTO gs_parallel.IF lv_counter < lv_package.APPEND gs_parallel TO lt_parallel.DELETE ct_user_param INDEX 1.lv_counter = lv_counter + 1.ELSE.EXIT.ENDIF.ENDLOOP.* Convert the input data into the INDX structure that is needed for the RFCCALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'EXPORTINGdata    = lt_parallelIMPORTINGindxtab = ct_rfcdata.IF lt_parallel IS INITIAL.CLEAR cs_before_rfc_exp-start_rfc.EXIT.ELSE.
* Inform task manager that an RFC can be started from the
* data compiledcs_before_rfc_exp-start_rfc = 'X'.ENDIF.ENDFORM.                    "before_rfc
*&---------------------------------------------------------------------*
*&      Form  in_rfc
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->IS_IN_RFC_IMP  text
*      -->ES_IN_RFC_EXP  text
*      -->IT_RFCDATA     text
*----------------------------------------------------------------------*
FORM in_rfcUSING    is_in_rfc_imp TYPE spta_t_in_rfc_impCHANGING es_in_rfc_exp TYPE spta_t_in_rfc_expct_rfcdata    TYPE spta_t_indxtab.DATA: ls_head_temp  TYPE zsfi_doc_head.DATA: lt_head_temp  TYPE STANDARD TABLE OF zsfi_doc_head.DATA: lt_out_temp   TYPE STANDARD TABLE OF zsfi_doc_head_o.DATA: lt_item_temp  TYPE STANDARD TABLE OF zsfi_doc_item.DATA: ls_parallel   TYPE zsfi_doc_head_run.DATA: lt_parallel   TYPE STANDARD TABLE OF zsfi_doc_head_run.DATA: gt_out_temp   TYPE STANDARD TABLE OF zsfi_doc_head_o.DATA: lv_errcode TYPE char8.DATA: lv_errdesc TYPE char250.* decode the data from the INDX Structure into the process work listCALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'EXPORTINGindxtab = ct_rfcdataIMPORTINGdata    = lt_parallel.*you own process logicLOOP AT lt_parallel INTO ls_parallel.CLEAR:lv_errcode,lv_errdesc,lt_item_temp,lt_head_temp,lt_out_temp.MOVE-CORRESPONDING ls_parallel TO ls_head_temp.APPEND ls_head_temp TO lt_head_temp.lt_item_temp = ls_parallel-item.CALL FUNCTION 'ZFIFM_RECEIPT_POSTING'IMPORTINGerrcode = lv_errcodeerrdesc = lv_errdescTABLESit_head = lt_head_tempit_item = lt_item_tempot_head = lt_out_temp.APPEND LINES OF lt_out_temp TO gt_out_temp.ENDLOOP.* repack output data for AFTER_RFC formCALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'EXPORTINGdata    = lt_parallelIMPORTINGindxtab = ct_rfcdata.COMMIT WORK.ENDFORM.                    "in_rfc
*&---------------------------------------------------------------------*
*&      Form  after_rfc
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->IT_RFCDATA             text
*      -->IF_RFCSUBRC            text
*      -->IF_RFCMSG              text
*      -->IT_OBJECTS_IN_PROCESS  text
*      -->IS_AFTER_RFC_IMP       text
*      -->ES_AFTER_RFC_EXP       text
*      -->CS_USER_PARAM          text
*----------------------------------------------------------------------*
FORM after_rfc USING it_rfcdata  TYPE spta_t_indxtabif_rfcsubrc TYPE sy-subrcif_rfcmsg   TYPE spta_t_rfcmsgit_objects_in_process TYPE spta_t_objects_in_processis_after_rfc_imp      TYPE spta_t_after_rfc_impCHANGING es_after_rfc_exp TYPE spta_t_after_rfc_expcs_user_param   .DATA: lt_out   TYPE STANDARD TABLE OF zsfi_doc_head_o.DATA: lt_parallel   TYPE STANDARD TABLE OF zsfi_doc_head_run.
* uppack RFC output data and add RFC reulsts to global dataCALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'EXPORTINGindxtab = it_rfcdataIMPORTINGdata    = lt_parallel.APPEND LINES OF lt_parallel TO gt_result.ENDFORM.                    "after_rfc
上面的demo 我分别使用loop和parallel (10线程)去创建会计凭证
创建1000条,运行时间分别为:95 sec 17 sec
如此一比较下来。多线程的效率提升还是很快的。对于没有升级到HANA的ECC 系统还是有很多提升空间的