Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Initialize large table

Status
Not open for further replies.

moulisea

Programmer
Oct 21, 2012
7
US
Hi,
can you help me in initializing a large table like below sample one

01 ws-a.
05 ws-b occurs 50000 times.
10 ws-c pic x(02).
10 ws-d pic s9(9)v99 comp-3.

currently I do an initialize ws-a for each policy and when I did a strobe it shows this init as a larger pct(like 10%) - when I tried like below it didnt help much

01 ws-a-t.
05 ws-c-t pic x(02).
05 ws-d-t pic s9(9)v99 comp-3.
initialize ws-a-t. then for every policy I used MOVE statement
move ws-a-t to ws-a (1:8)
move ws-a (1:8) to ws-a (9:8)
.....

If you have any better way, please let me know.

 
How often does this initialization need to happen (i.e. how many timer per program execution)?
 
Init should happen for each policy and there would be 2,000,000 policies.
 
create another array with same structure as the original one - set your program to initialize it once per run-unit.

On each call where the original array needs to be initialized, copy this new array onto it - it may prove to be faster.

If this is being done under CICS it may not work.

Regards

Frederico Fonseca
SysSoft Integrated Ltd

FAQ219-2884
FAQ181-2886
 
Thanks Frederico Fonseca. I tried the way you said like moving the 01 variable from cloned to the original table and that didnt fetch better result.
so looking for any other better option.
 
Which compiler is being used?

Look at the generated code and see how the compiler implemented the different initialization routines.
 
Try this...
01 ws-a.
05 filler.
10 filler value spaces pic x(02).
10 filler value +0 comp-3 pic s9(09)v99.
05 ws-b.
10 filler occurs 50000 times.
15 ws-c pic x(02).
15 ws-d pic s9(9)v99 comp-3.

for each policy...
move ws-a to ws-b.

You may get a warning message about moving a field to a part of itself but it works just fine since an alphanumeric move is done one byte ate a time from left to right and stops when the end of the shortest field is encountered.
 
Coboldeke - that may work in some compilers depending on the options used... but in most of the shops I worked, a developer that used that method would quickly be shown why that should never ever be done

Regards

Frederico Fonseca
SysSoft Integrated Ltd

FAQ219-2884
FAQ181-2886
 
Can I make the assumption that the 50000 table size is normally much, much larger than needed?

If so, you might want to use OCCURS 1 to 50000 DEPENDING ON current-inx.

Then, at the beginning of each policy, MOVE 1 to current-inx, and store your result in ws-b (current-inx) and add 1 to current-inx. (You are probably doing almost this much work anyway.)

At the culmination of a policy, subtract 1 from current-inx. If greater than 0, you will have a group with exactly the right number of occurrences, and you have obviated the need for initialization.

As previously asked, what compiler and operating system, please?

Tom Morrison
Micro Focus
 
"but in most of the shops I worked, a developer that used that method would quickly be shown why that should never ever be done"
Just curious - why would this method be discouraged?
 
The method was encouraged at the shop where I worked. It only generates one 6 byte MVC instruction to get the table initialized. I worked with IBM COBOL and never had a problem with this method in 35 years that I programmed. The only thing I saw in recent compiler versions was a warning message so you understood what you were doing.
 
1) An MVC command can only poccess 256 bytes. A 50000 entry table would require many thousands of such cummands.
2) Normally, the mainframe compiler would use an MVCL command, which can handle moves of upto 16MB. But that command will detect a "destructive" overlap, and refuse to execute, issuing an "O" condition. ("O" is the mnemonic for Odd, Overflow, or in this case, Overlap) In this case, the compiler detects the overlap, and generates either thousands of MVC's or a loop of MVC's which will execute thousands of times.

The OCCURS DEPENDING ON option or the same logic implemented in the programming algorithm is a far superior method.

BTW, when the MVCL command first became available to COBOL, I switched it on by setting the apropriate words in the Environment Division. It immediatly failed. It turned out that that particular computer model had a bug in the the microcode for MVCL, which caused it to fail in circumstances which the EE's probabley figured would be rare, but are frequetly obtained in COBOL programs, as in the subject of this discussion.
 
"In this case, the compiler detects the overlap, and generates either thousands of MVC's or a loop of MVC's which will execute thousands of times."

Not using a current COBOL compiler on Z/OS.

Just ran the following code:

Code:
       01  A-BIGGUN          PIC X(1000000). 
       01  FILLER REDEFINES A-BIGGUN.        
           05 FILLER PIC X.                  
           05 A-BIGGUN-1     PIC X(999999).  

           MOVE A-BIGGUN TO A-BIGGUN-1.        
           DISPLAY 'GOT THRU THE MOVE'.        
           GOBACK.

Which generates this code:
Code:
     LA    2,25(0,8)               A-BIGGUN-1         
     L     3,20(0,10)              PGMLIT AT +12      
     LA    4,24(0,8)               A-BIGGUN           
     L     5,16(0,10)              PGMLIT AT +8       
     MVCL  2,4                                        
     BC    14,348(0,11)            GN=15(00038C)      
     L     2,92(0,9)               TGTFIXD+92         
     L     15,176(0,2)             V(IGZCVMO )        
     LA    1,201(0,10)             PGMLIT AT +193     
     BASR  14,15

Abnd when executed, produces this output.
Code:
GOT THRU THE MOVE

The compile (IBM Enterprise COBOL for z/OS 4.2.0) issues this warning:
30 IGYPA3013-W Data items "A-BIGGUN (ALPHANUMERIC)" and "A-BIGGUN-1 (ALPHANUMERIC)" had overlapping storage. An overlapping move will occur at execution time.

The run returns an rc=0.

Took more time to fiddle with the Code tag than run the test . . .[[ponder]
Still don't quite have it right . . .
 
MVCL sets the condition code of "O", it does not cause an interupt or even set a return code. There is no way for the COBOL application to test this condition code. Perhaps IBM has changed this to allow the destructive overlap.

In the case of filling a table with a single value such as Spaces, High-Values or All 'x' (where x is any character), the MVCL will handle that well. If you do it that way, the COBOL compiler will generate the appropiate settings for the MVCL, then execute it. In fact, other than setting the condition code, MVCL appears to be a machine language implementation of the COBOL display (or group) item MOVE verb.
 

There is no way for the COBOL application to test this condition code. Perhaps IBM has changed this to allow the destructive overlap.
And there need be no way - it is just another instruction. . .

On this level of the compiler (Enterprise 4.2), a Warning is issued and the overlap is processed as expected (Detailed Earlier).
 
Yes, I understood that the COBOL compiler issues the warning. And since it gernerates the MVCL command anyway, I assume that in the new models (since 1973!) IBM has changed the microcode (and the documentation, I would hope) for the MVCL command. If this is so, and it surely must be, I would guess it was due to pressure from the COBOL community where such destructive overlapping moves are very common, almost always for initialization.

BTW, I believe modern compilers allow Value clauses on subscripted items, pushing the initialization to compile time, saving much work at execution time.
 
Back when I used to work in the MVS (z/OS) world (over 12 years ago), the last application I worked on included several large WS tables that needed to be initialized "for each [italics]policy[/italics]" and Strobe analysis also indicated that a disproportionately large percentage of time was being spent initializing the WS tables. Our tables, as I suspect is probably the case with yours, included a great many elementary items below the group level. The code was originally set up to loop through each of the OCCURRENCES of the group level and initialize each one. In terms of your example, it looked like this:
Code:
PERFORM VARYING INDX FROM 1 BY 1 UNTIL INDX > 50000
    INITIALIZE WS-B (INDX)
END-PERFORM

The experts we consulted suggested to alter the initialization as follows:
Code:
INITIALIZE WS-B (1)
PERFORM VARYING INDX FROM 2 BY 1 UNTIL INDX > 50000
    MOVE WS-B (1) TO WS-B (INDX)
END-PERFORM

and that significantly improved the efficiency of our table initialization. Not sure if this is still the case, but apparently each INITIALIZE of the group level WS-B was translated into individual MOVE statements to initialize each elementary item subordinate to the group. So, initializing each group was equivalent to a straight-line block of code initializing every single individual occurence of each elementary field in the table. Whereas the initializing the first was still the same, but MOVE-ing whole group levels for all subsequent occurrences of the WS-B group after the first was much more efficient. And of course, the suggestion of using a variable-length table (OCCURS DEPENDING ON) would be even more efficient, assuming you clear the table at the end of processing each "policy". If using variable-length tables makes you uncomfortable, you could simply keep track of the highest occurrence used for the previous policy to terminate the initialization loop. This value would start at the maximum occurs value for the very first policy. something like this:
Code:
INITIALIZE WS-B (1)
PERFORM VARYING INDX FROM 2 BY 1 UNTIL INDX > COUNT OF WS-B OR INDX > PREV-HIGHEST-USED
    MOVE WS-B (1) TO WS-B (INDX)
END-PERFORM

Code what you mean,
and mean what you code!
But by all means post your code!

Razalas
 
Suggest "someone" run/post some cpu monitoring tests and post the results and in which environment the tests were conducted.

I find it hard to believe the perform (any flavor) will use less cpu then the single long move. When a few of my teams tested this years ago, they tried may alternatives and were not able to get the performance of the overlapping move.
 
This is the way I do it, even for small tables:

1) Have a pointer to the highest entry currently used.

2) If another entry is required, increment the above pointer and initialize the new entry befor using.

3) On each processing cycle, reset the pointer to zero.

There are several advantages; the two most advantagous are that you never need to initialize the whole table unless it is used and that you always know how many entries there are if you need that information for other purposes, such as computing "y" when printing (or displaying) "page x of y".
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top