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 系统还是有很多提升空间的