乐趣区

关于sap:SAP-ABAP-写时拷贝Copy-on-Write策略的一个具体例子

值语义 (Value semantics) 和援用语义 (reference semantics) 形容了动态内存对象在多个变量援用它时, 能够体现的两种形式。

用于特定类型的动态内存对象的语义, 对该类型的对象如何耗费内存产生了重要影响。

实质上,应用值语义的援用变量总是有它本人的、它所援用的内存对象的惟一正本。值语义变量相似于动态变量;像动态变量一样,它间接绑定到它所代表的内存对象。只管变量只是一个援用,但在语义上它是内存对象自身。

相比之下,应用援用语义的援用变量被了解为指向内存对象的指针。内存对象在语义上独立于援用变量。该对象能够在许多这样的变量之间共享。

Value Semantics 的典型代表:

  • ABAP Internal Tables
  • Strings
  • Boxed Components

应用值语义解析对 ABAP 内表、字符串或 boxed 组件的屡次援用。这意味着:

  • 内表、字符串或 boxed 组件的每个变量都指向它本人的内存对象的独自正本。
  • 将内表、字符串或 boxed 组件调配给第二个 ABAP 变量会触发对象的复制操作,以便每个变量都有本人的对象正本。
  • 通过特定变量对内表、字符串或装箱组件所做的更改,对于已调配给同一对象的其余变量是不可见的。

因为外部表和字符串可能会变得十分大,ABAP 通过采纳 惰性复制 (有时也称为 写时复制 ) 策略 (Copy-On-Write) 来节俭复制工作量。

咱们来看一个具体的例子。

源代码如下:

REPORT z.

DATA: lv_size     TYPE abap_msize,
      lv_size1    LIKE lv_size,
      lv_consumed LIKE lv_size.

DATA: lt_table  TYPE TABLE OF tadir,
      lt_table1 LIKE lt_table.

SELECT * INTO TABLE lt_table FROM tadir.

cl_abap_memory_utilities=>get_total_used_size(IMPORTING size = lv_size).

WRITE:/ 'total consumed:' , lv_size.

lt_table1 = lt_table.

cl_abap_memory_utilities=>get_total_used_size(IMPORTING size = lv_size1).

lv_consumed = lv_size1 - lv_size.

WRITE:/ 'total consumed after =' , lv_consumed.

APPEND lt_table[1] TO lt_table.

CLEAR: lv_size.

cl_abap_memory_utilities=>get_total_used_size(IMPORTING size = lv_size).

lv_consumed = lv_size - lv_size1.
WRITE:/ 'total consumed after copy on write:', lv_consumed.

这个测试程序的 5 个关键点:

  1. 从数据库表 TADIR 里读取其全副数据,存储到内表 lt_table 内。打印以后应用程序所在的会话总共耗费的内存字节数。
  2. 将内表 lt_table 的内容复制给 lt_table1. 这里并不触发实在的内表间数据拷贝操作,因为内表 lt_table1 和 lt_table 此刻都指向同一块内存区域。
  3. 打印出以后应用程序所在的会话,同第一步执行结束后的内存增量。因为没有理论的数据拷贝操作,咱们能够判定,这个打印进去的值应该很小。

  1. 批改 lt_table 的值,之后,两个内表指向的内存区域不再是同一块,触发了 ABAP 的写时拷贝逻辑,造成了理论的内表拷贝操作,引起了大量的内存调配。
  2. 打印出第四步执行完后的应用程序内存增量。能够判定,因为 TADIR 数据库的全部内容从一个内表复制到另一个内表,因而这个增量的值和第一个步骤打印的值十分靠近。
退出移动版