SAP RFC不同设置性能以及RFC、WebService的性能对比

本文通过实测比较了RFC(RemoteFunctionCall)与WebService在不同序列化协议、数据量和调用次数下的性能,发现经典序列化器和BasXML性能较差,快速序列化效果最好,但需注意ECC6系统不支持快速序列化。同时指出WebService在某些场景下的性能表现。
Python3.8

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

本来RFC性能好于WebService是毋庸置疑的,但是最近总有兄弟说WebService或者Restful性能好于RFC,于是有了此篇文章,以正视听。

首先,在确定的服务器、客户端,接口逻辑和数据量一定的前提下,RFC的性能主要取决与两个地方,一是内表放到Tables还是Export下面,二是RFC的序列化协议。

83780d00a4decf3802b919c8a424359c.png

14904cdbc04ad8c7778648008f285d05.png

dd63e00f47c00d00e7c1a26071210d96.png

一般来说,如果协议是典型序列化器(Classic Serializer),内表放到Export和放到Tables两者之间性能差别是非常大的,在检查RFC函数的时候,系统也会警告提示:
35cd856f84a7942522ab806c106bccd7.png

如果是其他协议,则放到哪儿都是一样的。

为了直观的对比各个场景的性能差异,我写了一个简单的对比程序,在同一个系统/不同系统、Export参数/Tables参数、不同序列化协议、不同数据量和调用次数,以及WebService的运行时间对比。

对比结果如下,后面的数值是所用时间,单位为微秒:
首先是小数据量(100条)的单次调用
758cc2bb4a0682e373c1d9ed0b614b56.png

其次是大数据量(内表100000条)的单次调用de2dc25172c61b330e1fc97e114093e5.png

最后是小数据量(内表100条)的多次(100次)调用4425267d4bb765ca1a49590da16f670c.png

需要说明的是,程序运行在S4,而远程系统是ECC6,ECC6是不支持快速序列化的,所以跨系统RFC的快速序列化并没有特别的快。

结论:
1、如果是用Classic协议,内表一定不要在Export,否则性能极差。
2、BasXML协议是需要转成XML来传输的,性能不是太好。
3、快速序列化是性能最好的,但是老系统不支持,S4开始支持,如果可能请尽量使用此序列化协议。
4、WebService性能不如RFC,小数据量且调用次数较少时可以使用。
5、Restful因为可以自定义传输数据的格式,方法不同性能差别也很大,所以就不做比较了,但是大概可以参考WebService的性能。

附测试程序和函数:

REPORT ztestrfc NO STANDARD PAGE HEADING.


DATA: itab TYPE TABLE OF dd02l.
DATA: ws_proxy TYPE REF TO zwsco_zget_dd02l.
DATA: ws_input TYPE zwszget_dd02l.
DATA: ws_respo TYPE zwszget_dd02lresponse.
DATA: eoutab TYPE zwscnvmbt_dd02l_t,
      toutab TYPE zwstable_of_dd02l,
      initab TYPE zwsdd02l_tab WITH HEADER LINE.
DATA: t1 TYPE i,
      t2 TYPE i.


PARAMETERS: p_dbcnt TYPE sy-dbcnt DEFAULT 3000.
PARAMETERS: p_count TYPE i DEFAULT 1.


AT SELECTION-SCREEN OUTPUT.
  %_p_dbcnt_%_app_%-text = '内表条数'.
  %_p_count_%_app_%-text = '连续调用次数'.


START-OF-SELECTION.
  WRITE: '内表条目数:',p_dbcnt.
  WRITE: / '调用次数:',p_count.
  SKIP.


  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'E'
      IMPORTING
        eoutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'正常函数调用Export:', t1.


  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'T'
      TABLES
        toutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'正常函数调用Table:', t1.




***RFC Classic序列化器
  SKIP.
  WRITE '本系统RFC' COLOR 1.
  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'DS4_185_C'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'DS4_185_C'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'E'
      IMPORTING
        eoutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'Classic序列化器 Export:', t1.


  GET RUN TIME FIELD t1.
  DO p_count TIMES.


    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'DS4_185_C'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'DS4_185_C'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'T'
      TABLES
        toutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'Classic序列化器 Table:', t1.




***BasXML
  SKIP.
  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'DS4_185_B'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'DS4_185_B'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'E'
      IMPORTING
        eoutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'BasXML Export:', t1.


  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'DS4_185_B'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'DS4_185_B'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'T'
      TABLES
        toutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'BasXML Table:', t1.




***强制BasXML序列化器
  SKIP.
  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'DS4_185_O'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'DS4_185_O'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'E'
      IMPORTING
        eoutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'强制BasXML Export:', t1.


  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'DS4_185_O'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'DS4_185_O'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'T'
      TABLES
        toutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'强制BasXML Table:', t1.




***快速序列化器
  SKIP.
  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'DS4_185_F'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'DS4_185_F'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'E'
      IMPORTING
        eoutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'快速序列化器 Export:', t1.




  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'DS4_185_F'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'DS4_185_F'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'T'
      TABLES
        toutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'快速序列化器 Table:', t1.




***不同系统 ClassicRFC
  SKIP.
  WRITE '跨系统RFC' COLOR 1.




***Classic
  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'HSD_125_C'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'HSD_125_C'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'E'
      IMPORTING
        eoutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'Classic序列化器 Export:', t1.


  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'HSD_125_C'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'HSD_125_C'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'T'
      TABLES
        toutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'Classic序列化器 Table:', t1.




***BasXML
  SKIP.
  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'HSD_125_B'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'HSD_125_B'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'E'
      IMPORTING
        eoutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'BasXML Export:', t1.


  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'HSD_125_B'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'HSD_125_B'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'T'
      TABLES
        toutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'BasXML Table:', t1.




***强制BasXML序列化器
  SKIP.
  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'HSD_125_O'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'HSD_125_O'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'E'
      IMPORTING
        eoutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'强制BasXML Export:', t1.


  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'HSD_125_O'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'HSD_125_O'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'T'
      TABLES
        toutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'强制BasXML Table:', t1.




***快速序列化器
  SKIP.
  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'HSD_125_F'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'HSD_125_F'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'E'
      IMPORTING
        eoutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'快速序列化器 Export:', t1.




  GET RUN TIME FIELD t1.
  DO p_count TIMES.
    CALL FUNCTION 'RFC_CONNECTION_CLOSE'
      EXPORTING
        destination          = 'HSD_125_F'
      EXCEPTIONS
        destination_not_open = 1.


    CLEAR itab[].
    CALL FUNCTION 'ZGET_DD02L' DESTINATION 'HSD_125_F'
      EXPORTING
        dbcnt  = p_dbcnt
        param  = 'T'
      TABLES
        toutab = itab.
  ENDDO.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30)'快速序列化器 Table:', t1.


***WebService
   APPEND INITIAL LINE TO initab.
   ws_input-toutab-item[] = initab[].


  SKIP.
  ws_input-dbcnt = p_dbcnt.
  ws_input-param = 'E'.
  GET RUN TIME FIELD t1.
  TRY .
      CREATE OBJECT ws_proxy.
      DO p_count TIMES.
        CALL METHOD ws_proxy->zget_dd02l
          EXPORTING
            input  = ws_input
          IMPORTING
            output = ws_respo.
      ENDDO.
    CATCH cx_root.
  ENDTRY.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30) 'WebService Export:', t1.


  ws_input-dbcnt = p_dbcnt.
  ws_input-param = 'T'.
  GET RUN TIME FIELD t1.
  TRY .
      CREATE OBJECT ws_proxy.
      DO p_count TIMES.
        CALL METHOD ws_proxy->zget_dd02l
          EXPORTING
            input  = ws_input
          IMPORTING
            output = ws_respo.
      ENDDO.
    CATCH cx_root.
  ENDTRY.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(30) 'WebService Table:', t1.

两个系统的函数是一样的:
4d06c7cf6f8110df67a3c9a8e9c2fe58.png

6b6502522164384ce0f1c6f1817ed4ee.png

FUNCTION zget_dd02l.
*"----------------------------------------------------------------------
*"*"本地接口:
*"  IMPORTING
*"     VALUE(DBCNT) TYPE  SY-DBCNT OPTIONAL
*"     VALUE(PARAM) TYPE  CHAR1 OPTIONAL
*"  EXPORTING
*"     VALUE(EOUTAB) TYPE  CNVMBT_DD02L_T
*"  TABLES
*"      TOUTAB STRUCTURE  DD02L OPTIONAL
*"----------------------------------------------------------------------
  CHECK dbcnt IS NOT INITIAL.


  CLEAR: eoutab[],toutab[].
  SELECT SINGLE * INTO toutab FROM dd02l.
  IF param = 'T'.
    DO dbcnt TIMES.
      APPEND toutab.
    ENDDO.
  ELSE.
    DO dbcnt TIMES.
      APPEND toutab TO eoutab.
    ENDDO.
  ENDIF.
ENDFUNCTION.

89ab67ac226266be925e7b99043f2b84.jpeg

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值