CA OPS/MVS: Static Variables usage in OPS/REXX programs - Best Practice.

Document ID : KB000028142
Last Modified Date : 14/02/2018
Show Technical Document Details

Introduction:

When writing OPS/REXX programs, there are usually multiple ways of achieving the same objective. However, some coding techniques may have unintended side effects that can seriously impact the overall performance of the code. This article describes how the misuse of Static Variables might create an undesired impact in CPU utilization

Description:

The following two AOF MSG rules perform similar functions:

Example rule 1)MSG ADASTATICS
)INIT
GLVTEMPM.L1.L2.A = 1
GLVTEMPM.L1.L2.B = 1
GLVTEMPM.L1.L2.C = 1
GLVTEMPM.L1.L2.D = 1
GLVTEMPM.L1.L2.E = 1
GLVTEMPM.L1.L2.F = 1
GLVTEMPM.L1.L2.G = 1
GLVTEMPM.L1.L2.H = 1
GLVTEMPM.L1.L2.I = 1
GLVTEMPM.L1.L2.J = 1
GLVTEMPM.L1.L2.K = 1
GLVTEMPM.L1.L2.L = 1
GLVTEMPM.L1.L2.M = 1
GLVTEMPM.L1.L2.N = 1
GLVTEMPM.L1.L2.O = 1
GLVTEMPM.L1.L2.P = 1
GLVTEMPM.L1.L2.Q = 1
GLVTEMPM.L1.L2.R = 1
GLVTEMPM.L1.L2.S = 1
GLVTEMPM.L1.L2.T = 1
GLVTEMPM.L1.L2.U = 1
GLVTEMPM.L1.L2.V = 1
GLVTEMPM.L1.L2.W = 1
GLVTEMPM.L1.L2.X = 1
GLVTEMPM.L1.L2.Y = 1
GLVTEMPM.L1.L2.Z = 1
)PROC
if GLVTEMPM.L1.L2.A > 0 then
GLVTEMPM.L1.L2.A = GLVTEMPM.L1.L2.A + 1
if GLVTEMPM.L1.L2.B > 0 then
GLVTEMPM.L1.L2.B = GLVTEMPM.L1.L2.B + 1
if GLVTEMPM.L1.L2.C > 0 then



Example rule 2)MSG ADASTATICS
)INIT
itemp = OPSVALUE('GLVTEMPM.L1.L2.A','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.B','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.C','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.D','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.E','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.F','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.G','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.H','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.I','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.J','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.K','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.L','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.M','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.N','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.O','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.P','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.Q','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.R','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.S','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.T','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.U','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.V','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.W','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.X','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.Y','U',1)
itemp = OPSVALUE('GLVTEMPM.L1.L2.Z','U',1)
)PROC
if OPSVALUE('GLVTEMPM.L1.L2.A','V') > 1 then
temp = OPSVALUE('GLVTEMPM.L1.L2.A','A',1)
if OPSVALUE('GLVTEMPM.L1.L2.B','V') > 1 then
temp = OPSVALUE('GLVTEMPM.L1.L2.B','A',1)
if OPSVALUE('GLVTEMPM.L1.L2.C','V') > 1 then
temp = OPSVALUE('GLVTEMPM.L1.L2.C','A',1)


When looking at the PROC sections of each rule, which are both fairly small, it appears as if there are no significant differences between the two in terms of performance. However, example rule 1 consumes more than twice as many CPU resources as example rule 2 for each event processed in the PROC section. This occurs because the code in the INIT section is connected to the performance of the PROC section. The OPS/REXX statement GLVTEMPM.L1.L2.A = 1 in the INIT section has the unintended side effect of creating three uninitialized simple variables (L1, L2, and A), which, because they are used in the INIT section, are treated as Static Variables.

Now let us take a look at the code in the PROC section of the example rule 1:

if GLVTEMPM.L1.L2.A > 0 then
GLVTEMPM.L1.L2.A = GLVTEMPM.L1.L2.A + 1

The code references each of the  Static Variables (as part of the standard OPS/REXX compound variable name resolution) as well as the temporary global variable three times. Since the overhead of evaluating Static Variables is fairly high, this coding style results in significantly higher CPU consumption than the optimal coding in example rule 2, which specifies the temporary global variable names as character strings.

Also notice that in example rule 2, different temporary variables (itemp and temp) are used to avoid using the Static Variable (itemp) in the PROC section.

In addition, the OPSVALUE ADD function used in example rule 2 not only provides a serialized add function, but it also reduces the number of accesses to the temporary global variables by two thirds, which further reduces the overhead.

While the above examples may be contrived examples used to illustrate the point being made, CA-OPS/MVS Customer Support has seen the former technique used in an MSG * rule before. The result was an inefficient rule that consumed significantly more CPU resources than it should have.

Additional Information:

Static and Global Variables are fully documented in our CA OPS/MVS AOF Rules User Guide.