[an error occurred while processing this directive]
HP OpenVMS Systems Documentation |
HP Pascal for OpenVMS
|
Previous | Contents | Index |
Data items that are smaller than 32 bits might impose a performance penalty, due to the additional instructions required to access them. The compiler will attempt to reorder loads and stores that manipulate adjacent items smaller than 32 bits to minimize the number of memory references required.
For performance reasons, HP Pascal on OpenVMS I64 and OpenVMS Alpha systems will allocate Boolean and enumerated types as longwords in unpacked records or arrays. On OpenVMS VAX systems, you have to explicitly request this with a DCL qualifier or the corresponding attribute.
You should avoid any explicit size attributes on subrange types. While
it is true that [BYTE] 0..255 is smaller than 0..255 (which would
allocate 4 bytes, since it is a subrange of INTEGER), the additional
overhead of accessing the byte-sized subrange might be than the extra 3
bytes of storage. Using the BIT attribute on subranges is even less
effective in terms of the extra instructions required to manipulate a
13-bit integer subrange inside a record. Use these attributes only
where needed.
9.7.5 Converting Existing Records
When moving code from an OpenVMS VAX system to an OpenVMS I64 or
OpenVMS Alpha system, you probably want to make sure that you are
getting the best performance on the new system. To do that, you must
use natural alignment on your record types.
9.7.6 Applications with No External Data Dependencies
If your application has no external data dependencies (such as no stored binary data files, no binary data transmitted to some external device), then the conversion is as simple as:
Depending on your data types, the removal of any PACKED keywords or attributes may make little improvement in performance. For example, a PACKED ARRAY OF REAL is identical in size and performance to an unpacked ARRAY OF REAL.
HP Pascal has two features to help you identify poorly aligned records and how often they are used:
program a; type r = packed record f1 : boolean; f2 : integer; end; begin end. |
$ pascal/usage=performance test.pas f1 : boolean; .........^ %PASCAL-I-COMNOTSIZ, Component is not optimally sized at line number 4 in file DISK$:[DIR]TEST.PAS;32 f2 : integer; .........^ %PASCAL-I-COMNOTALN, Component is not optimally aligned at line number 5 in file DISK$:[DIR]TEST.PAS;32 %PASCAL-S-ENDDIAGS, PASCAL completed with 2 diagnostics |
$ pascal/list/show=structure_layout test.pas |
Comments Offset Size ----------- ----------- ----------- 5 Bytes R {In PROGRAM A} = PACKED RECORD Size 0 Bytes 1 Bit F1 : BOOLEAN Align 1 Bit 4 Bytes F2 : INTEGER END |
If your application has external data dependencies, the process is more involved, since you have to isolate and understand the dependencies.
Possible steps when porting the code include:
This should produce the same behavior on the OpenVMS I64 or OpenVMS Alpha system as you had on your OpenVMS VAX system with the following exception: Using D_Floating data on Alpha systems only provides 53 bits of mantissa instead of 56 bits as on VAX systems; using D_floating data on OpenVMS I64 systems causes the compiler to convert to/from D_Floating data and IEEE T_Floating data to actually perform any needed operations.
You then have to identify which records in your program have external data dependencies. These include binary files (for example, FILE OF xxx), shared memory sections with other programs, and binary information passed to a library routine (such as an OpenVMS item list).
You can immediately begin to convert records without external data dependencies into optimal format (for example, remove any unneeded PACKED keywords and attributes as described earlier).
You need to classify records with external dependencies further into:
Isolate records that you cannot change into their own environment file by using /ALIGN=VAX, /ENUM=BYTE, and /FLOAT=D_FLOAT. You can also attach the ALIGN and ENUMERATION_SIZE attributes to the TYPE or VAR sections that define these records. In this case, you need to also change any uses of the DOUBLE datatype to the D_FLOAT datatype, to ensure that the proper floating format is used.
You do not need to isolate the record if it uses the PACKED keyword, since PACKED records are identical regardless of the /ALIGN or /ENUM qualifiers. Nevertheless, isolating the records with dependencies might be useful in the future if you eventually intend to change the format.
For records that you might change, you need to decide whether it is worthwhile to convert the record and any external binary data. If the record is of low use and you have a large quantity of external data, the cost of conversion is probably too high. If a record is of high use but is mostly aligned, then the conversion also may not be worthwhile. However, a high-use record that is poorly aligned suggests conversion of external data regardless of the amount of effort required.
There are two types of poorly aligned records:
type t = packed record f1,f2 : integer; end; |
type t = record f1,f2 : integer; end; |
The /USAGE=PERFORMANCE and /SHOW=STRUCTURE_LAYOUT DCL qualifiers can be helpful for identifying poorly aligned records.
For PACKED keywords, you can compile with and without the PACKED keyword to see if the fields are positioned at the same offsets or not.
You have classified the records with external data dependencies into:
For the well-aligned records, no additional work is needed now, but be aware that you still have an external data dependency that might cause problems if you add fields to the record in the future.
Isolate records that are not being converted into the same environment file or into the TYPE or VAR sections where you placed the records that you could not convert.
For records that are worth converting, you need to plan how to convert the external binary data or cooperating software. For cooperating software, you need to ensure that it gets modified so it views the record with the "natural" layout. You can determine the layout by using the /SHOW=STRUCTURE_LAYOUT command-line option described above. For binary data, you need to write a conversion program.
Converting existing binary data involves writing a program that reads the existing data into a poorly aligned record, copies the data into a well aligned record, and then writes out the new record.
A simple conversion program would look like:
program convert_it(oldfile,newfile); [align(vax),enumeration_size(byte)] type oldtype = packed record { Existing record fields } end; type newtype = record { Record fields reorganized for optimal alignment } end; var oldfile = file of oldtype; newfile = file of newtype; oldvar : oldtype; newvar : newtype; begin reset(oldfile); rewrite(newfile); while not eof(oldfile) do begin read(oldfile,oldvar); { For each field, sub-field, etc. move the data } newvar.field1 := oldvar.field1; newvar.field2 := oldvar.field2; write(newfile,newtype); end; close(oldfile); close(newfile); end. |
Notice the "type" keyword before the definition of the "newtype" type. Without this keyword, "newtype" would be in the same type definition part as "oldtype" and would be processed with the same ALIGN and ENUMERATION_SIZE settings.
If you have embedded DOUBLE data, you must use the D_FLOAT predefined type in the "oldtype" definition, since the default on OpenVMS I64 systems is for T_floating format and the default on OpenVMS Alpha systems is for G_Floating format. The compiler does not allow a simple assignment of a D_FLOAT value to a T_FLOAT or G_FLOAT variable. You need to use the CNV$CONVERT_FLOAT routine provided with OpenVMS to convert the floating data.
This appendix lists the error conditions detected by the STATUS and STATUSV functions, their symbolic names, and the corresponding values. The symbolic names and their values are defined in the file SYS$LIBRARY:PASSTATUS.PAS, which you can include with a %INCLUDE directive in a CONST section of your program. To test for a specific condition, you compare the STATUS or STATUSV return values against the value of a symbolic name.
The symbolic names correspond to some of the run-time errors listed in Appendix C; however, not all run-time errors can be detected by STATUS.
There is a one-to-one correspondence between the symbolic constants returned by STATUS or STATUSV documented in PASSTATUS.PAS and the OpenVMS condition code values in SYS$LIBRARY:PASDEF.PAS. The following routine shows how to map the return value of STATUS to its corresponding condition code located in PASDEF.PAS:
FUNCTION CONVERT_STATUS_TO_CONDITION(STAT:INTEGER):INTEGER; BEGIN CONVERT_STATUS_TO_CONDITION := 16#218644 + STAT * 8; END; |
Table A-1 lists the symbolic names and the values returned by the STATUS and STATUSV functions and explains the error condition that corresponds to each value.
Name | Value | Meaning |
---|---|---|
PAS$K_ACCMETINC | 5 | Specified access method is not compatible with this file. |
PAS$K_AMBVALENU | 30 | "String" is an ambiguous value for the enumerated type "type". |
PAS$K_CURCOMUND | 73 | DELETE or UPDATE was attempted while the current component was undefined. |
PAS$K_DELNOTALL | 100 | DELETE is not allowed for a file with sequential organization. |
PAS$K_EOF | --1 | File is at end-of-file. |
PAS$K_ERRDURCLO | 16 | Error occurred while the file was being closed. |
PAS$K_ERRDURDEL | 101 | Error occurred during execution of DELETE. |
PAS$K_ERRDUREXT | 127 | Error occurred during execution of EXTEND. |
PAS$K_ERRDURFIN | 102 | Error occurred during execution of FIND or FINDK. |
PAS$K_ERRDURGET | 103 | Error occurred during execution of GET. |
PAS$K_ERRDUROPE | 2 | Error occurred during execution of OPEN. |
PAS$K_ERRDURPRO | 36 | Error occurred during prompting. |
PAS$K_ERRDURPUT | 104 | Error occurred during execution of PUT. |
PAS$K_ERRDURRES | 105 | Error occurred during execution of RESET or RESETK. |
PAS$K_ERRDURREW | 106 | Error occurred during execution of REWRITE. |
PAS$K_ERRDURTRU | 107 | Error occurred during execution of TRUNCATE. |
PAS$K_ERRDURUNL | 108 | Error occurred during execution of UNLOCK. |
PAS$K_ERRDURUPD | 109 | Error occurred during execution of UPDATE. |
PAS$K_ERRDURWRI | 50 | Error occurred during execution of WRITELN. |
PAS$K_EXTNOTALL | 128 | EXTEND is not allowed for a shared file. |
PAS$K_FAIGETLOC | 74 | GET failed to retrieve a locked component. |
PAS$K_FILALRCLO | 15 | File is already closed. |
PAS$K_FILALROPE | 1 | File is already open. |
PAS$K_FILNAMREQ | 14 | File name must be specified in order to save, print, or submit an internal file. |
PAS$K_FILNOTDIR | 110 | File is not open for direct access. |
PAS$K_FILNOTFOU | 3 | File was not found. |
PAS$K_FILNOTGEN | 111 | File is not in generation mode. |
PAS$K_FILNOTINS | 112 | File is not in inspection mode. |
PAS$K_FILNOTKEY | 113 | File is not open for keyed access. |
PAS$K_FILNOTOPE | 114 | File is not open. |
PAS$K_FILNOTSEQ | 115 | File does not have sequential organization. |
PAS$K_FILNOTTEX | 116 | File is not a text file. |
PAS$K_GENNOTALL | 117 | Generation mode is not allowed for a read-only file. |
PAS$K_GETAFTEOF | 118 | GET attempted after end-of-file has been reached. |
PAS$K_INSNOTALL | 119 | Inspection mode is not allowed for a write-only file. |
PAS$K_INSVIRMEM | 120 | Insufficient virtual memory. |
PAS$K_INVARGPAS | 121 | Invalid argument passed to an HP Pascal Run-Time Library procedure. |
PAS$K_INVFILSYN | 4 | Invalid syntax for file name. |
PAS$K_INVKEYDEF | 9 | Key definition is invalid. |
PAS$K_INVRECLEN | 12 | Record length nnn is invalid. |
PAS$K_INVSYNBIN | 37 | "String" is invalid syntax for a binary value. |
PAS$K_INVSYNENU | 31 | "String" is invalid syntax for a value of an enumerated type. |
PAS$K_INVSYNHEX | 38 | "String" is invalid syntax for a hexadecimal value. |
PAS$K_INVSYNINT | 32 | "String" is invalid syntax for an integer. |
PAS$K_INVSYNOCT | 39 | "String" is invalid syntax for an octal value. |
PAS$K_INVSYNREA | 33 | "String" is invalid syntax for a real number. |
PAS$K_INVSYNUNS | 34 | "String" is invalid syntax for an unsigned integer. |
PAS$K_KEYCHANOT | 72 | Changing the key field is not allowed. |
PAS$K_KEYDEFINC | 10 | KEY(nnn) definition is inconsistent with this file. |
PAS$K_KEYDUPNOT | 71 | Duplication of key field is not allowed. |
PAS$K_KEYNOTDEF | 11 | KEY(nnn) is not defined in this file. |
PAS$K_KEYVALINC | 70 | Key value is incompatible with file's key nnn. |
PAS$K_LINTOOLON | 52 | Line is too long; exceeds record length by nnn characters. |
PAS$K_LINVALEXC | 122 | LINELIMIT value exceeded. |
PAS$K_NEGWIDDIG | 53 | Negative value in width or digits (of a field width specification) is invalid. |
PAS$K_NOTVALTYP | 35 | "String" is not a value of type "type". |
PAS$K_ORGSPEINC | 8 | Specified organization is inconsistent with this file. |
PAS$K_RECLENINC | 6 | Specified record length is inconsistent with this file. |
PAS$K_RECTYPINC | 7 | Specified record type is inconsistent with this file. |
PAS$K_RESNOTALL | 124 | RESET is not allowed for an internal file that has not been opened. |
PAS$K_REWNOTALL | 123 | REWRITE is not allowed for a file opened for sharing. |
PAS$K_SUCCESS | 0 | Last file operation completed successfully. |
PAS$K_TEXREQSEQ | 13 | Text files must have sequential organization and sequential access. |
PAS$K_TRUNOTALL | 125 | TRUNCATE is not allowed for a file opened for sharing. |
PAS$K_UPDNOTALL | 126 | UPDATE is not allowed for a file that has sequential organization. |
PAS$K_WRIINVENU | 54 | WRITE operation attempted on an invalid enumerated value |
Previous | Next | Contents | Index |