Copyright 2024 - BV TallVision IT

Abap memory is a mysterious theme, as it probably is with any programming language. Memory is something that is around and a developer can't do much to control it. Globally defined variables can be accessed from all FORM routines. A function module can not access globally defined variables from the calling program. Or can it ? What about a class ? Here's a few bits and bobs explained.

Abap memory and "memory span" can maybe be best understood by understanding namespacing effects. A technical object has a unique name, and it's uniqueness is checked in it's namespace. A transaction code and a report name can have the very same name, because they are not in the same namespace. The variables in your report are also in a "namespace".

 So Abap memory with it's global variables have a memory span of the report itself. The debugger can reveal what is available and what is not at any given location in your program. You will see that the call stack shows quite an impressive list of calling reports. Each of these reports can have globally defined variables with the same name, and the values of these variables will depend on where you are in the coding.

Globally declared variables from the program will not be available in the function module that is called. Function modules reside in a group and these groups are factually a report. As any report, global variables can be declared and when a function module from the group is called, it could set a value that will be available the next time the function module is called. Or even available for other function module calls (to the same function group).

Here's something you won't see very often: instead of DATA: you can also declare your variabele in a routine as STATICS:. What this will do is bombard the locally defined variabele a global variabele. However one that is not available outside the routine. So if you were to use it as a counter, you can increase the counter when you are about to leave the routine and find an increased counter when you next call the routine. 

So is there no way to get access to the variables of a calling program (program that called you) ?

Object oriented programming - and memory matters: Abap has come a long way and Object Oriented programming hopped on the train somewhere. The Object Oriented paradigm has a clear answer to memory management matters. Memory garbage collection is something the Abap developer does not have to look after - the system does it for us.

You're in a tight spot somewhere, and you have some data that needs to be carried accross to some other bit of coding, which is called some time later. Can the system hang on to it for a while ? It's not the most elegant way, but it can be a way out: data can be exported to memory, or even the database if needed. The choice is yours. To export data to the database, a unique key is required, which will of course also need to be available at the receiving end of the export (the import).

It's been a while, but some 10 years back I tried to fill an internal table with data, just to see how much it would take. The table structure of EKPO with just under 200 fields, was appended to 10.000 times. The system didn't even flinch. Memory is pretty much without limit. The problem with large data sets is performance, not actual size. May have something to do with memory-swapping or paging, where pages of memory are stored to a database location somewhere - which is again performance killing. Thus: performance problems before memory problems.

Having said that: there is a way to keep a tap on the memory consumption of your report. Is it a big report ? An interface with a lot of data ? You can get the percentage of available memory that is used by your report as well as the actual memory size through function module /SDF/MEMORY_INFO. Or the function modules called by this module. The /SDF/MEMORY_INFO module returns a dandy readible list of numbers which are all labeled and all serve a purpose. I found the "Extended Memory" results handy.

Example report - show memory consuption

Below I've set up a simple report that adds data to an internal table. As the table grows and grows, memory information is displayed. The report:

REPORT zabapcadabra_memory_buster.

DATA: gt_result TYPE  /sdf/is_output_t,
      gw_result TYPE /sdf/is_output,
* A test-table with a considerable line size
      lt_test TYPE STANDARD TABLE OF char1024.

DEFINE memory_info_dump.
* The action on this macro: increase the LT_TEST consumption,
* get memory consumption results and report them.
  clear: lt_test[].
  DO &1 TIMES.
    APPEND 'Something' TO lt_test.
  ENDDO.
* Get memory consumption data
  clear: gt_result[].
  call function '/SDF/MEMORY_INFO'
    importing
      result = gt_result.
* Show gathered data, focus on the Extended memory
  describe table lt_test lines sy-dbcnt.
  write: / 'Internal table LT_TEST has', sy-dbcnt, 'rows of 1Kb'.
  loop at gt_result into gw_result.
    if  gw_result-metric(1) = 'E'.
      write: /(50) gw_result-metric, gw_result-value.
    endif.
  endloop.
  skip.
END-OF-DEFINITION.

START-OF-SELECTION.

  memory_info_dump 50.
  memory_info_dump 500.
  memory_info_dump 5000.
  memory_info_dump 50000.
  memory_info_dump 500000.
  memory_info_dump 1000000.

The results from the /SDF/MEMORY_INFO module reveal a lot more than just the Extended memory matters. But this demo focuses on this only. Report output;

Internal table LT_TEST has         50  rows of 1Kb
Extended Memory:Current used(%)                    3
Extended Memory:Current used(KB)                   163840
Extended Memory:In Memory(KB)                      4190208

Internal table LT_TEST has        500  rows of 1Kb
Extended Memory:Current used(%)                    3
Extended Memory:Current used(KB)                   163840
Extended Memory:In Memory(KB)                      4190208

Internal table LT_TEST has      5.000  rows of 1Kb
Extended Memory:Current used(%)                    4
Extended Memory:Current used(KB)                   172032
Extended Memory:In Memory(KB)                      4190208

Internal table LT_TEST has     50.000  rows of 1Kb
Extended Memory:Current used(%)                    6
Extended Memory:Current used(KB)                   266240
Extended Memory:In Memory(KB)                      4190208

Internal table LT_TEST has    500.000  rows of 1Kb
Extended Memory:Current used(%)                    27
Extended Memory:Current used(KB)                   1171456
Extended Memory:In Memory(KB)                      4190208

Internal table LT_TEST has  1.000.000  rows of 1Kb
Extended Memory:Current used(%)                    52
Extended Memory:Current used(KB)                   2179072
Extended Memory:In Memory(KB)                      4190208

So what's showing ? The last information block shows a total available memory of 4.190.208Kb of which 2.318.336Kb is consumed by the program. That's 55%.