【13】SAP ABAP性能优化 - 共享对象 (Shared Objects)

news2024/11/25 4:28:01

1. 背景

“共享对象”是NetWeaver 6.40以上版本ABAP编程中的一个技术,在"共享对象"概念出来之前,在ABAP中可以通过EXPORT和IMPORT这样的关键字去访问服务器上的共享内存,实现不同进程中的数据交互。有关这方面的概念,我在之前的博客《SAP ABAP性能优化 - 内存管理 (ABAP Memory vs. SAP Memory》中已有介绍。

今天,让我们一起看下“共享对象”的概念和实现。

2. 基础概念

2.1 共享内存(Shared Memory)

共享内存是应用服务器上的一个内存区域,该服务器的所有ABAP程序都可以访问该内存区域。在引入共享对象之前,ABAP程序可以使用EXPORT和IMPORT语句访问该内存区域,但这种方式是不支持类的实例或匿名数据对象的实例这种“面向对象”的概念的,大白话说就是,你不可能从一个进程EXPORT一个类的实例,然后IMPORT到另个一个进程。

随着6.40版本中共享对象的引入,共享内存得到了扩展,包括可以存储共享对象的共享对象内存。共享对象内存的大小由abap/shared_objects_size_MB配置文件参数决定。这也就意味着,我们可以实现类的实例在不同进程中的共享。

2.2 共享对象(Shared Object)

共享对象也即是共享内存中的对象,用于存储类的实例和匿名数据对象。

2.3 启动共享内存的类(Shared Memory-Enabled Classes)

如果想让一个类可以被存放在共享内存中,那么在定义这类时,要声明其属性是“Shared Memory-Enabled”。

 关键字是SHARED MEMORY ENABLED。 

CLASS zcl_gg_shma_root DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC
  SHARED MEMORY ENABLED.

  PUBLIC SECTION.

ENDCLASS.

2.4 共享域和域的实例(Area and Area Instance)

除了共享类,这里还有一个“共享域”的概念,可以把它理解成一个“控制层”,可以控制共享对象的一些特定的属性,例如“创建方式”,“生命周期”等等。

可以使用事务代码SHMA来创建和管理区域及其属性, 可以使用SHMM来监测共享域和共享实例的状态。

域和共享对象的root类链接,共享对象的root类可以包含单独的数据和开启用共享内存的类的其他实例,或对匿名数据对象的引用。

2.5 域类和域的句柄(Area and Area Handles)

当在事务SHMA中定义一个域时,将生成一个具有相同名称的全局最终区域类,作为CL_SHM_AREA的子类。类CL_SHM_AREA本身是CL_ABAP_MEMORY_AREA的直接子类。

在ABAP程序中,使用生成的域类的方法访问域。

这个同名的全局类中的静态方法可以将ABAP程序(或其内部会话)绑定到共享内存中的域实例(附加方法)。

绑定将创建一个域类的实例作为区域句柄,并同时创建一个锁。

ABAP程序可以使用域句柄访问绑定区域实例版本,从而访问存储在那里的共享对象。区域句柄还包含用于删除连接或锁的方法(分离方法)。

3. 示例

下面,让我们用一个最简单的例子来看一下,共享对象的实现。

目标,通过共享对象的方式,将一个内表的数据,有一个session传递到另一个session。

3.1 定义共享对象类

定义全局类ZCL_GG_SHMA_ROOT并声明其开启了共享内存。

定义要传递的数据mt_sflight为此类的属性,并为此属性添加set和get方法。与此同时,实现接口if_shm_build_instance,目的是可以实现此共享类可以作为域的构建函数类。也就是说,可以实现共享域的自动构建。当启动自动构建共享域时,会隐式开启一个内部的ABAP session来调用root类中的这个if_shm_build_instance~build方法。

这个例子中,为了简化共享域的构建步骤,我们使用自动构建的方式。

CLASS zcl_gg_shma_root DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC
  SHARED MEMORY ENABLED.

  PUBLIC SECTION.
    INTERFACES if_shm_build_instance.

    METHODS get_data
      EXPORTING et_sflight TYPE flighttab.

    METHODS set_data
      IMPORTING it_sflight TYPE flighttab.

  PRIVATE SECTION.
    DATA mt_sflight TYPE flighttab.
ENDCLASS.



CLASS zcl_gg_shma_root IMPLEMENTATION.
  METHOD get_data.
    et_sflight = mt_sflight.
  ENDMETHOD.


  METHOD set_data.
    mt_sflight = it_sflight.
  ENDMETHOD.


  METHOD if_shm_build_instance~build.
    DATA lo_root TYPE REF TO zcl_gg_shma_root.

    TRY.
        " Request a Write Lock
        DATA(lo_area_handle) = zcl_gg_shma_area=>attach_for_write( ).
      CATCH cx_shm_exclusive_lock_active
            cx_shm_version_limit_exceeded
            cx_shm_change_lock_active
            cx_shm_parameter_error
            cx_shm_pending_lock_removed.
        " handle exception
    ENDTRY.

    CREATE OBJECT lo_root AREA HANDLE lo_area_handle.

    " Initialize data in root class
    lo_root->set_data( VALUE #( ) ).

    lo_area_handle->set_root( lo_root ).

    " Release Change Lock and Flag for COMMIT
    lo_area_handle->detach_commit( ).
  ENDMETHOD.
ENDCLASS.

3.2 定义共享对象域

使用事务代码SHMA创建共享域ZCL_GG_SHMA_AREA,共享域创建时,会自动创建一个同名的全局类,用于控制共享域和共享对象。

指定相关共享域的属性,此处声明共享类ZCL_GG_SHMA_ROOT为共享域ZCL_GG_SHMA_AREA的root class完成共享类与共享域的链接。

同时声明,这个共享域可以通过ZCL_GG_SHMA_ROOT的Build方法自动构建,自动构建的场景是“Autostart if read request and invalidated”,就是只要有读此共享域的请求时,或是共享域失效时,都会自动重新构建此共享域。

 我们可以看一下,自动生成共享域全局类ZCL_GG_SHMA_AREA中的一些方法,有三大类:

  • 构建共享域,设定获取共享对象
  • 请求释放共享锁
  • 释放共享域

我们在程序中,可以通过这些方法,来控制使用的共享域。

3.3 数据写入

编写程序A,用于向共享对象中写入数据。

*&---------------------------------------------------------------------*
*& Report ZGG_SHMA_SESSION_A
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zgg_shma_session_a.

TRY.
    " Direct Call of Area Constructor
    zcl_gg_shma_area=>build( ).
  CATCH cx_root.
    EXIT.
ENDTRY.

TRY.
    " Request a Change Lock
    DATA(lo_area_handle) = zcl_gg_shma_area=>attach_for_update( ).
  CATCH cx_root.
    EXIT.
ENDTRY.

DATA(lo_root) = CAST zcl_gg_shma_root( lo_area_handle->get_root( ) ).


" set data into shared memory object
SELECT * FROM sflight INTO TABLE @DATA(lt_sflight).
lo_root->set_data( CORRESPONDING #( lt_sflight ) ).

lo_area_handle->set_root( lo_root ).
lo_area_handle->detach_commit( ).

WRITE 'SFLGHT data has been added to shared memory object'.

3.4 数据读取

编写程序B,用于从共享对象中获取数据。

*&---------------------------------------------------------------------*
*& Report ZGG_SHMA_SESSION_B
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zgg_shma_session_b.

TRY.
    " request a read lock
    DATA(lo_area_handle) = zcl_gg_shma_area=>attach_for_read( ).
  CATCH cx_root INTO DATA(lx_exc).
    EXIT.
ENDTRY.

" get data from shared memory object
DATA(lo_root) = CAST zcl_gg_shma_root( lo_area_handle->get_root( ) ).
lo_root->get_data( IMPORTING et_sflight = DATA(lt_sflight) ).

" remove shared lock
lo_area_handle->detach( ).

cl_demo_output=>display_data( lt_sflight ).

3.5 测试

运行程序A,然后运行程序B,可以发现,在程序B执行的dialog session仍然可以读到程序A中写入共享域中共享对象的数据。

程序A运行结果:

程序B运行结果:

4. 扩展

上面的例子中,对于理解共享内存的概念很有帮助,但其实也是存在一定的问题的,例如例子中,对于写入共享对象的数据其实是一直存在的,如果再次启动session B,仍然是可以读取到的。

如果完成数据传递后,我们的目的就达到了,那么应当在session B访问到数据后,销毁共享内存中的数据,否则是对shared memory的一种浪费。

针对上面的例子,我们可以在SHMM中看到,及时运行完程序B后,仍然可以监控到这个共享域以及其中的数据。

因而,在实际开发中,我们要考虑放入共享内存中数据的生命周期,对共享对象的使用有着更加规范的方式。

4.1 手动启动域

因为,我们也可以选择不自动启动域的创建,仅仅手动启动域,配置参数如下:

不配置自动创建域,就不需要在root class中实现这个if_shm_build_instance~build方法了。

CLASS zcl_gg_shma_root_manual DEFINITION PUBLIC FINAL CREATE PUBLIC
  SHARED MEMORY ENABLED.

  PUBLIC SECTION.
    METHODS get_data
      EXPORTING et_sflight TYPE flighttab.

    METHODS set_data
      IMPORTING it_sflight TYPE flighttab.

  PRIVATE SECTION.
    DATA mt_sflight TYPE flighttab.
ENDCLASS.



CLASS zcl_gg_shma_root_manual IMPLEMENTATION.
  METHOD get_data.
    et_sflight = mt_sflight.
  ENDMETHOD.


  METHOD set_data.
    mt_sflight = it_sflight.
  ENDMETHOD.
ENDCLASS.

在进程C中,手动启动共享域,并向共享对象中写入数据。

REPORT zgg_shma_session_c.

DATA lo_root_manual TYPE REF TO zcl_gg_shma_root_manual.

TRY.
    " create a new area instance (it could be specified with a unique name) and get handles
    DATA(lo_area_handle) = zcl_gg_shma_area_manual=>attach_for_write( ).

    " Request a Change Lock for this area using an existing instance
    " lo_area_handle = zcl_gg_shma_area_manual=>attach_for_update( ).

    CREATE OBJECT lo_root_manual AREA HANDLE lo_area_handle.

    " set data into shared memory object
    SELECT * FROM sflight INTO TABLE @DATA(lt_sflight).
    lo_root_manual->set_data( CORRESPONDING #( lt_sflight ) ).

    " link shared object to area handle
    lo_area_handle->set_root( lo_root_manual ).

    " release change lock
    lo_area_handle->detach_commit( ).

    WRITE 'SFLGHT data has been added to shared memory object'.
  CATCH cx_root INTO DATA(lx_exc).
    cl_fins_cfin_msg=>output_exception_msg( lx_exc ).
    EXIT.
ENDTRY.

要区分attach_for_write和attach_for_update的不同,这两个方法都可以返回一个共享域实例的句柄。通常而言,使用attach_for_write去创建一个新的共享域的实例(通过SHMM可观测到新实例的创建),而用attach_for_update去获取一个已经创建域的实例的句柄,在此基础上更新其所存储的共享对象的内容。

因而,当需要有多个共享实例时,要指定其instance_name用于区分。当然,如果仅需要一个共享实例,则可以默认使用default的name。

4.2 手动销毁域

在进程D中,读取共享域,并在读取结束后,销毁域的实例。

REPORT zgg_shma_session_d.

TRY.
    " request a read lock
    DATA(lo_area_handle) = zcl_gg_shma_area_manual=>attach_for_read( ).

    " get data from shared memory object
    DATA(lo_root_manual) = CAST zcl_gg_shma_root_manual( lo_area_handle->get_root( ) ).
    lo_root_manual->get_data( IMPORTING et_sflight = DATA(lt_sflight) ).

    " remove shared lock
    lo_area_handle->detach( ).

    " Deactivate the instance, else we create waste instances in shared memory
    zcl_gg_shma_area_manual=>invalidate_instance( ).

  CATCH cx_root INTO DATA(lx_exc).
    cl_fins_cfin_msg=>output_exception_msg( lx_exc ).
    EXIT.
ENDTRY.

cl_demo_output=>display_data( lt_sflight ).

4.3 共享类的扩展

在上面的例子中,我们仅仅展示了一个共享对象root,在实际使用中,如果需要多个共享对象,那么则可以将这些共享对象申明为root的属性,形成层级关系。

通过root来链接共享域,来统一管理,在此不再赘述,大家可以参考系统中已有的共享域。

5. 小结

本文介绍了ABAP编程中“共享对象”的概念,我们除了传统的EXPORT和IMPORT,还可以通过“共享对象”实现在不同ABAP进程间数据的传递。通过事物代码SHMA创建共享域,通过事物代码SHMM监控共享域。

6. 参考资料

  • 共享对象(ABAP关键字文档): Shared Objects - ABAP Keyword Documentation (sap.com)
  • 共享对象(SAP 帮助门户) : SAP Help Portal

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/848510.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5分钟,带你了解低代码开发

在传统的理解中,企业内数字化应用的开发和迭代应该是 IT 部门的工作,但事实并非如此。一方面,激烈的市场竞争和反复出现的疫情给数字化提出了新的要求;另一方面,五花八门的零代码、低代码工具正如雨后春笋一般出现&…

【设计模式】——模板模式

什么是模板模式? 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern),在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行…

代码审计-RCE命令执行漏洞审计

代码审计必备知识点: 1、代码审计开始前准备: 环境搭建使用,工具插件安装使用,掌握各种漏洞原理及利用,代码开发类知识点。 2、代码审计前信息收集: 审计目标的程序名,版本,当前环境(系统,中间件…

通达信上涨回调选股公式,趋势指标和摆动指标结合使用

在前面的文章中,介绍了赫尔均线 (HMA)和随机RSI(StochRSI),这两个指标分别属于趋势指标和摆动指标。趋势指标和摆动指标是技术分析中常用的两类指标,用于分析市场的走势和波动,它们的计算方法、应用场景都是有区别的。今天利用两类…

架构实践方法

一、识别复杂度 将主要的复杂度问题列出来,然后根据业务、技术、团队等综合情况进行排序,优先解决当前面临的最主要的复杂度问题。对于按照复杂度优先级解决的方式,存在一个普遍的担忧:如果按照优先级来解决复杂度,可…

从安装 Seata 开始的分布式事务之旅 springboot集成seata

从安装 Seata 开始的分布式事务之旅 介绍什么是 Seata? 安装 Seata Server下载 Seata Server 发行版配置Seata解压文件配置Seata的yml文件把配置文件config.txt加载到nacos上修改config.txt文件加载到nacos上 启动Seata服务正常启动查看启动日志打开控制台页面 启动…

使用 PowerShell 将 Excel 中的每个工作表单独另存为独立的文件

导语:在日常工作中,我们经常需要处理 Excel 文件。本文介绍了如何使用 PowerShell 脚本将一个 Excel 文件中的每个工作表单独另存为独立的 Excel 文件,以提高工作效率。 1. 准备工作 在开始之前,请确保已经安装了 Microsoft Exc…

IMV7.0

一、背景 经历了多个版本,基础内容在前面,可以使用之前的基础环境: v1: https://blog.csdn.net/wtt234/article/details/132139454 v2: https://blog.csdn.net/wtt234/article/details/132144907 v3: https…

Vue调用硬件 接口报错

谷歌浏览器调用硬件报错 报错原因 调用身份证读卡器,使用谷歌浏览器 读卡器硬件的接口 有几率是被谷歌拦截 所以报错 在谷歌地址栏输入 chrome://flags/ 搜索 block 找到这个选项 切换状态之后重启浏览器即可 当时找的这篇文章 解决问题 参考链接 如果大家的问题没…

2023集成电路产业发展与产教融合高峰论坛会议顺利举行

8月5日,由中国半导体行业协会和市政府共同主办,天水师范学院、天水华天科技股份有限公司、杭州加速科技有限公司承办的2023集成电路产业发展与产教融合高峰论坛在天水举行。天水市委书记冯文戈,教育部学生服务与素质发展中心副主任方伟&#…

untiy 连接两个UI或一段固定一段跟随鼠标移动的线段

注意,仅适用于UI,且Canvas必须是Camera模式,不能用在3D物体上,3D物体请使用LineRenender 先创建一个图片,将锚点固定在左边 然后在脚本中添加如下内容 public RectTransform startObj;//起点物体public RectTransfor…

软件测试基本准侧与方法摘录

软件测试基本准侧与方法的摘录(应用实例待补充) 写在最开始:“测试是为发现错误而执行程序的过程”。————《软件测试的艺术》 🤩 本文中很多概念描述摘抄自还有很多概念没有列举。已写的部分概念缺少相应的实例,尚…

Java课题笔记~ Spring事务的程序举例环境搭建

举例:购买商品 trans_sale 项目 本例要实现购买商品,模拟用户下订单,向订单表添加销售记录,从商品表减少库存。 实现步骤: Step0:创建数据库表 创建两个数据库表 sale , goods sale 销售表:…

2021年03月 Python(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

一、单选题(共25题,每题2分,共50分) 第1题 下列哪个操作不能退出IDLE环境? A:AltF4 B:CtrlQ C:按ESC键 D:exit() 正确的答案是:B:CtrlQ 解…

LM2596S-adj电源芯片应用电路

手边有两块降压电源模块,使用芯片为LM2596S-adj,手册中给的使用电路为: 市面上买到的模块为: 电路为: 对比后发现苏守坤博客中存在错误,原博客中实物图应为输出可调的电源模块,博主所画原理…

深入理解PyTorch中的NoamOpt优化器

深入理解PyTorch中的NoamOpt优化器 作者:安静到无声 个人主页 今天,我们将深入探讨一个在自然语言处理领域广泛使用的优化器——NoamOpt。这个优化器是基于PyTorch实现的,并且在"Attention is All You Need"这篇论文中首次提出。…

若依后台管理系统06

哈喽!大家好,我是旷世奇才李先生 文章持续更新,可以微信搜索【小奇JAVA面试】第一时间阅读,回复【资料】更有我为大家准备的福利哟,回复【项目】获取我为大家准备的项目 最近打算把我手里之前做的项目分享给大家&#…

Rivian:一家已经在全球电动汽车领域站稳脚跟的热门电动汽车公司

来源:猛兽财经 作者 :猛兽财经 总结: (1)Rivian(RIVN)是全球电动汽车市场的主要参与者,由于全球电动汽车市场的不断增长和亚马逊(AMZN)的持续支持&#xf…

Blob的一些使用 - 下载、图片预览、切片上传

Blob Blob: 前端专门用于支持文件操作的二进制对象 File: 一种特殊的Blob对象 文件下载 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

Qt应用开发(基础篇)——信号槽 Signals and Slots

一、前言 Qt成为我们今天拥有的灵活而舒适的工具&#xff0c;除了友好和能够快速开发设计师界面&#xff0c;信号槽机制是最大的核心特征&#xff0c;也是区别于其他开发框架最大的优势。 Qt的信号槽作用于两个对象之间的通信。当一个对象发生了改变&#xff0c;它希望其他关心…