How to port from IBM AIX to IBM z/OS

This article discusses possible issues that you may encounter when you port XL C/C++ applications from the IBM® AIX® platform to the IBM® z/OS® platform. It also discuses ideas and suggestions for getting better performance for the application on the z/OS platform after the porting is completed.

Porting applications from one platform to another is not always a painless and seamless transition. Many issues can cause problems in the porting process. However, it is possible to reduce and alleviate these problems, and to make the porting process smoother and more error-free, especially with a plan.

After moving the application from one platform to another, the application should be tuned to get the maximum performance on the new platform. Usually, the new platform has features and restrictions that the old platform did not have. Tuning to the new platform can help bring benefits that were not present on the original platform, and take advantage of the new hardware.

Share:

Rajan Bhakta (rbhakta@ca.ibm.com), Staff Software Developer, IBM

Rajan Bhakta works for IBM. He has five years of development experience for IBM XL C. He is currently the ISO C Standards representative for Canada, and the C representative for IBM in INCITS. He is also the Technical Architect for z/OS XL C/C++.



Zach Zylawy (zazylaw@ca.ibm.com), Staff Software Developer, IBM

Photo of Zach ZylawyZach Zylawy works for IBM. He has four years of experience working with the IBM z/OS C/C++ test team experience, as well as five years of development in z/OS and IBM AIX C++.



17 August 2010

Also available in Portuguese Spanish

Overview

This article presents suggestions about how to solve some common issues that you may encounter when you port a C or C++ application from IBM® AIX® to the IBM® z/OS® platform. It also discusses ways to improve the performance of the application on z/OS when it has been ported.

The topics covered in the porting section are:

  • External dependencies
  • Hardware-specific code
  • Alignment dependencies
  • Floating-point formats
  • Character encodings
  • Language extensions
  • DLLs
  • Language levels
  • Programming environment

The topics covered in the performance section are:

  • When to optimize
  • Compile time compared to execution time
  • Compile time modifiers
  • Execution time environment
    • Inter-language interoperability
    • Responsibilities of the runtime
  • Compiler-based execution time modifiers
  • System-based execution time modifiers
  • Memory usage
  • Source-level performance and accuracy aids
    • Built-in functions
    • Floating-point formats
  • Loading time
    • DLPA (dynamic link pack area)
    • VLF/LLA (virtual look-aside facility/library lookaside)
  • Runtime options
  • I/O Performance

Porting

Before you begin the porting process

Porting any non-trivial application from one platform to another is usually fairly involved. However, some preparation before you start the AIX to z/OS porting project makes the project smoother and minimizes compiler errors on z/OS.

Note: Most of these suggestions apply to any port between platforms, and are not specific to a port from AIX to z/OS porting.

Address compiler messages

The first and most straightforward step to take when you port an application from AIX to z/OS is to address all of the diagnostic messages produced by the compiler on AIX. Although program behavior might still be correct with these warnings, their presence indicates a potential problem that might arise when the application is compiled on z/OS. Responding to the warnings before you port can prevent potential problems on z/OS, and save you hours of debugging time trying to track down a problem.

External dependencies

When you port, you also need to identify if header files or external programs that are not available on z/OS are called or used by your application, and modify your application's source code appropriately if this is the case.

Code types

The next porting step is to locate and identify any areas in your source program that use the following types of code:

  • Hardware-specific code: any code dealing with hardware aspects that are different between platforms. For example, any ASM (Assembly) statements need to be changed to match the target platform ASM language and syntax.
    • Byte order ("Endian-ness") is the same between AIX and z/OS, so no changes need to be made with respect to this.
  • Alignment-specific code: structure layouts might be different between AIX and z/OS. For example, a zero-length bitfield as the first member on AIX results in different size and alignment then on z/OS. The C structure shown in Listing 1 has an alignment of four, and a size of four on AIX, but has an alignment of one and a size of one on z/OS.
    • This is not usually a problem, because most well-written code is not critically dependent on structure sizes and alignment.
    • The AGGR (aggregate) option shows the aggregate map, which displays the structure layout.
Listing 1. Code with different alignment and size on AIX and z/OS
struct A {
   int :0;
   char a;
};
  • Floating point ranges: The ranges of some floating-point types are different on AIX and on z/OS. For example, the long double type might have different ranges, depending on the floating-point format that you use. The available floating-point formats are also different and are discussed later in the paper.
    • This is not usually an issue unless specific precision and results are required.

These types of hardware-dependent constructs are the most difficult part of the porting process, because they typically represent actual new code that you must write. However, the IBM® compiler provides facilities to ease this process, such as the FLOAT(IEEE|HEX) compiler option, as well as various #pragma's that allow you to modify the alignment and packing of structures.

Character encodings

The character set used by default is also different on AIX and z/OS. AIX uses ASCII encoding, but z/OS uses EBCDIC (Extended Binary Coded Decimal Interchange Code). You can use the ASCII|NOASCII option on z/OS to encode characters in ASCII. However, you still need to pay careful attention to this part of porting, because character encodings can be a very sensitive and hard-to-diagnose source of bugs.

The main issue for different character set encodings is to look for code that depends on numeric values or patterns of numeric values for the characters. For example, the code fragment shown in Listing 2 returns true for ASCII but false for EBCDIC if the variable contains the letter "A".

Listing 2. Code that checks for an ASCII character
if (is_this_char_variable_the_capital_letter_A == 65) {

A suitable modification of such code is shown in Listing 3.

Listing 3. Code that checks for an EBCDIC character
if (is_this_char_variable_the_capital_letter_A == ‘A’) {

Other common patterns depending on ASCII character encoding are capitalizing strings and scanning for letters (as opposed to numbers or special characters) by looking at ranges.

Language extensions

You also need to be aware that not all of the language extensions that are available on AIX are currently available on z/OS (and vice versa), although IBM is continually bridging the gap between what is available on the two platforms. Features such as OMP/SMP (Open Multi-Processing support/Symmetric Multiprocessing) and AltiVec (a floating point and integer SIMD (single instruction, multiple data) instruction set) are not available on z/OS, nor are all of the GCC (GNU Compiler Collection) compatibility extensions. To check which features are available on z/OS, see the z/OS XL C/C++ Language Reference linked in the Resources section.

DLLs

Dynamic link library (DLL) creation also differs between the two platforms. DLLs on z/OS rely on a compiler-generated text file, called a Definition Sidedeck, which by convention has the file extension .x. Definition Sidedecks are exclusive to z/OS, and you must generate one for each of the DLLs that you create on z/OS. These sidedecks are for inclusion on the link step of any application that uses one or more symbols from the DLL.

For more information about DLLs, see the "Build and use a DLL" section in the "Binding z/OS XL C/C++ Programs" chapter of the z/OS XL C/C++ User’s Guide linked in the Resources section.

Language levels

Finally, the language levels available during compilation on XL C/C++ for AIX are also available on XL C/C++ for z/OS. For C, however, AIX uses xlC stanzas to set the language level, while z/OS uses a compiler option (if you are using the c89/cxx utility instead of the xlC utility, which was introduced on z/OS V1R7).

To make the porting simpler for the project personnel, maintainers, and developers who are familiar with UNIX®, use USS (UNIX System Services) instead of MVS (Multiple Virtual Storage). Porting is possible in both environments, but USS is more like a traditional UNIX environment, and is familiar to developers with experience on AIX. The POSIX (Portable Operating System Interface for UNIX) environment is set up when using USS.


Performance enhancements

After you port the application, you will need to do some tuning to take advantage of the benefits that z/OS offers beyond its reliability and robustness. Some of the performance enhancements listed in this section are also available and apply across the XL C/C++ compilers on all platforms.

However, performance tuning should be the final step in the porting process. The most important part of the porting is to get the application to work properly. You can lose a lot of time tracking down bugs on prematurely optimized code. So, it is best to do the optimization tuning after you successfully port.

"Premature optimization is the root of all evil" -- C.A.R. Hoare

Improving performance is a complex matter and there are many techniques to do so. Some quick hints to improve the performance of your ported application follow, with more detailed options in later sections.

The resources at the end of this article can give more in-depth information on these and other performance improvement techniques that are beyond the scope of this paper.

You can obtain most of the performance enhancements through the compiler optimization options on z/OS, just like AIX. As with other platforms and compilers, there is generally a trade-off between compile time and execution time.

Compile time compared to execution time

There is a relative balance between the time spent compiling a program versus the time it takes to run the resulting compiled program. In general, the longer it takes to compile a program (using optimization), the faster the program will run. Note that this relationship is NOT linear, nor is it always the case that longer compilation time results in faster execution time. For example, sometimes there are certain programs where a lower level of optimization can result in faster execution time.

As a developer, you can do some performance experimentation, and achieve a fair trade-off between compile and execution time. By experimenting with compiler options, you can uncover what set of optimizations are right for your particular program. IBM tools such as the Performance Analyzer can help you monitor, analyze, and report on application performance.

In general, during development, you should use no optimization or low optimization to facilitate quick build turnaround times and debugging support. All builds for testing or production, however, should be compiled with the optimization level at which you intend to ship the final product.

Most of the optimization compiler options available under XL C/C++ for AIX are also available on XL C/C++ for z/OS, such as:

  • O2, O3, O4, and O5
  • IPA, HOT, PDF1, and PDF2
  • INLINE, ARCHITECTURE, and TUNE

However, it is usually worthwhile to spend some time fine tuning these options on the new platform, because architectural differences might cause a different set of options to be better on z/OS. To provide more performance benefits after porting, do not just use the identical optimization settings that you used on AIX. This is due to hardware differences between the platforms, and the optimization opportunities created for the optimizer by these differences.

Compile time performance

Compile time performance can be improved by using the following guidelines:

  • Ensure that the application has a well-ordered search path for header files. For example, each user header file is in the first directory of the user header file search path.
  • Specify the correct OE option to find the right header files in datasets or in the USS file system. For example, if you are in USS and using files, specify OE. If you are in the MVS environment and using datasets, specify NOOE. For more information on the OE option, see the z/OS XL C/C++ User’s Guide linked in the Resources section.
    • Use the system header files from z/OS USS (instead of partitioned datasets) to improve compilation time.
  • If you are working in USS, give each user a separate mountable file system to avoid I/O contention.
  • Use the binder to enable rebinding modules for small changes.

Note: The binder has larger symbol name length limitations than the linker.

When tuning your program, remember to keep in mind that z/OS is optimized for I/O throughput first and foremost, so you can get the biggest performance gains by focusing on this strength of the z/OS platform.

Runtime performance

Unlike AIX, z/OS uses a managed runtime called the Language Environment (LE). The Language Environment creates a single runtime environment for multiple high-level languages including:

  • C/C++
  • COBOL
  • PL/I
  • Language Environment enabled assembler programs

With a single runtime environment, incompatibilities between language-specific runtime environments are eliminated. This means that COBOL and C applications, for example, can communicate efficiently and easily together given the right settings. Moreover, you can create applications with component programs written in a variety of languages. The end result is code that runs faster, is less prone to errors, and is easier to maintain.

Some of the Language Environment's functions include:

  • DLL loading
  • Static initialization for reentrant programs
  • Handling library calls such as printf() and malloc()

However, most of the time, the fact that you are using Language Environment will be transparent to programmers, and presents few differences for developers coming from an AIX background. You can find more information on LE in the z/OS Language Environment Concepts Guide linked in the Resources section.

You can improve runtime performance by adhering to the following guidelines:

  • Generally, if a lot of small functions are often called (like the get and set methods in C++ objects), use the XPLink feature to use a different form of linkage that should improve the runtime performance of this type of application. The language runtime libraries have XPLink versions of functions to take full advantage of the benefits that the XPLink feature provides.
  • Use the -qinfo=als option on AIX before porting to z/OS to help ensure that the code is following ANSI aliasing rules. This option is available on XL C/C++ V10.1 and later. It lists potential ANSI aliasing violations in the source code, and the probable locations of these violations.
    • If you have no ANSI aliasing violations, this gives the compiler more optimization opportunities at higher compiler optimization levels.
    • If you have functional problems when using compiler optimizations, try using NOANSIALIAS to see if the code may not be following ANSI aliasing rules in cases where the -qinfo=als option did not find any problems (because the -qinfo=als option cannot find all cases). If performance is important, this option should not be used in production builds, and instead you should correct all of the ANSI aliasing violations.
  • Use higher levels of optimization and profile directed feedback. Higher optimization levels make the compiler do more application analysis, giving you more opportunities for runtime performance improvements. Profile directed feedback results in tuning for representative workloads for additional runtime performance benefits.
  • Put the load dataset in DLPA, and the cache lookup in VLF/LLA. These z/OS concepts allow faster loading and lookups. These concepts are discussed in more detail later in this article. Your z/OS System Programmer can help you implement this.
  • If your C program has no dependency on the Language Environment, use the METAL compiler option for C (Metal C). Metal C allows Language Environment-independent code that can avoid the overhead of going through the managed run time.
    • Please note that not all C library functions are available in Metal C. See the z/OS Metal C Programming Guide and Reference linked in the Resources section for details.
  • Use the maximum common ARCH/TUNE option level that is supported by the hardware that your application will be running on. This enables additional instructions, and exploits the hardware better. For example, if you are deploying your application to three machines that support ARCH 6, 9, and 8 respectively, then compile your application with ARCH(6), the maximum ARCH level supported by all three machines.

Application memory usage

Memory usage is often also a consideration. Many options are available for reducing the size of the modules and objects. The application can use reentrancy and DLLs to reduce the memory footprint of multiple invocations of an application and the shared parts of various applications. At a lower level, the COMPRESS option can reduce the size of generated objects. Also, ensure that constants are truly constant, and use the ROCONST and ROSTRING compiler options to place the constants in read-only memory. This makes it easier to debug problems, and to free up writable static sections for other purposes.

Source-level runtime performance improvements

Some techniques that involve modifying the application source code can be used for performance enhancements. For the biggest improvement, as mentioned earlier in this article, make sure that the source code follows the rules presented under the ANSIALIAS compiler option to obtain the maximum benefits of higher level optimizations.

Built-in functions

Hardware built-ins allow the compiler to use prepackaged inline assembly code to perform common operations that would otherwise require a function call. The benefit of using built-ins is that you eliminate the overhead of function prologues and epilogues, which can add up to a lot of overhead. This can significantly increase application execution speed if, for example, the built-ins are used in a loop that is called many times. In addition to removing the function prologues and epilogues, the compiler can better optimize code that makes use of built-ins.

It is not strictly necessary to use the hardware built-ins directly: IBM provides built-in functions to allow users to call common functions.

These built-in functions are provided through the language standard library headers like:

  • abs()
  • floor()
  • strcpy()

These functions map directly to hardware built-ins, thereby providing performance opportunities without explicit user intervention.

These built-in functions are provided through the language standard library headers like:

  • stdlib.h
  • math.h
  • decimal.h

The z/OS XL C/C++ Programming Guide (linked in the Resources section) has more information on built-in functions, and their underlying hardware built-ins.

The compiler uses the ARCH option to determine which built-ins are available on your hardware. Higher ARCH values utilize a higher numbers of built-ins. In other words, the newer your z/OS hardware, the more built-ins are available to you.

Although most built-in functions used by the XL C compiler are shared between AIX and z/OS, there are differences between the XL C++ built-in functions used on each platform. Explicit use of built-in functions in your source code on AIX might cause "undefined symbol" errors when you compile them on z/OS.

The z/OS XL C/C++ Programming Guide (linked in the Resources section) contains a list of built-in functions that are available on z/OS (for both C and C++).

Built-ins exist for many common programming operations, as well as for manipulating several common and IBM-specific data types, such as the floating point data types.

The floating point data types supported on z/OS are:

  • Decimal: Allows up to 31 digits and represents decimal numbers exactly.
  • Decimal Floating Point: Represents decimal numbers exactly and compactly.
    • For example, long long __d64_to_long_long(_Decimal64);
  • Hexadecimal Floating Point: Base 16. Different precision ranges, but same exponent ranges for floating point types.
  • Binary Floating Point: Follows the IEEE-754 specification.

The z/OS Principles of Operation book (linked in the Resources section) has very detailed information about all of the hardware built-ins.

Some built-ins simply perform type conversions in hardware instead of software (which greatly speeds execution time), as shown in Listing 4.

Listing 4. Built-in type conversions
int __srstu(unsigned short *op1, unsigned short *op2, unsigned short pattern, 
   unsigned short **found_char);

This built-in searches for a character pattern within substrings. Normally this would be implemented in a function, which if called thousands of times would create a lot of performance overhead due to the high number of function calls. The IBM compiler searches for opportunities to use this built-in instead, thus eliminating the overhead of function prologues and epilogues and allowing code motion and other optimizations which may not have otherwise been available around the built-in.

System/OS optimization

The environment where the application runs can also be used to help improve application performance. Many environment aspects on z/OS can help speed up loading programs, searching for libraries, and executing the program itself.

LPA/DLPA

The Link Pack Area (and Dynamic LPA) is essentially an area of memory on z/OS systems that allows the system programmer to load libraries and modules into it, in order to make them resident in memory for all users. This greatly increases the load and startup performance of these libraries and modules for all users of the system. The z/OS system administrator can set this up for your application.

Using the LPA and DLPA, the libraries and modules are effectively preloaded for anyone that needs to use them. Normally each call to a library or module requires the system to find and load them, which can add up to a lot of overhead for anything commonly used by a large number of users or applications, so the DLPA can result in dramatic performance increases.

Programs intended to reside in LPA/DLPA must be compiled with the RENT compiler option to make the program reentrant if they are not already naturally reentrant.

LLA/VLF

In conjunction with the LPA/DLPA, you can use the library lookaside (LLA) and virtual lookaside facility (VLF) to greatly speed up performance on the system overall.

Commonly used indices and lookup tables are stored and optimized into memory, greatly reducing I/O activity by the O/S, and thereby speeding up the system overall.

In summary, LLA and VLF are used to speed up the lookup of files and datasets on a system, while LPA and DLPA are used to speed up the loading of libraries and modules on a system.

When LLA/VLF and LPA/DLPA are used together, the process of finding and loading modules and libraries becomes extremely streamlined.

You can adjust various runtime options and test performance to try to increase application performance. For example:

  • HEAP
  • STACK
  • STORAGE

The z/OS Language Environment Programming Guide (linked in the Resources section) contains detailed reference information about these runtime variables. It also contains suggestions about which variables to use, depending on the type of application that you have.

Most of these runtime options increase performance at the cost of Direct Access Storage Device (DASD) space, which is often desirable these days because storage space is relatively cheap.

Note: DASD is the z/OS term for what is essentially a hard drive.

I/O performance

z/OS is already generally considered a top-of-the-line system when it comes to I/O performance and workload throughput. This does not mean that you cannot still extract more performance out of I/O operations. The "I/O Performance Considerations" chapter of the z/OS XL C/C++ Programming Guide (linked in the Resources section) has several specific hints and tips about how to optimize I/O operations on both datasets and USS/HFS (that is UNIX) files on z/OS. Note that a fair number of these tips apply to C/C++ (or any language) in general, not just to XL C/C++ for z/OS.

z/OS provides you (as a developer) with the ability to use memory files. These are files that stay resident in memory while being used, thus eliminating the need for much slower reads and writes to actual DASD storage. Memory files on z/OS are sort of equivalent to memory maps and shared memory maps on AIX.

Hiperspace files are another type of memory file that you can use. Hiperspace files reside in a special type of memory that does not use an application’s address space. This means that you can have very large memory files in 32-bit applications without reducing the amount of memory available to the program. Note that Hiperspace files are not available in 64-bit applications.


What you have learned

The porting of C and C++ applications from AIX to z/OS can be easy and, with careful tuning, can result in comparable performance while still capturing the benefits unique to the z/OS hardware and software stack.

There are a number of methods to improve the performance of the application on z/OS. This includes improving the load, search, and execution performance of the application, along with reducing the time and overhead of I/O operations of the application.

Resources

Learn

  • Get great information in the z/OS Internet Library. Learn much more detailed functionality with these important z/OS developer and programmer manuals:
    • z/OS C/C++ User’s Guide
    • z/OS C/C++ Programming Guide
    • z/OS C/C++ Language Reference
    • z/OS C/C++ Runtime Library Reference
    • z/OS Principles of Operations
    • z/OS Language Environment Programming Guide
  • Find out more about z/OS:
  • Find out more about AIX:
  • Learn about other applications in the IBM Rational Software Delivery Platform, including collaboration tools for parallel development and geographically dispersed teams, plus specialized software for architecture management, asset management, change and release management, integrated requirements management, process and portfolio management, and quality management. You can find product manuals, installation guides, and other documentation in the IBM Rational Online Documentation Center.
  • Visit the Rational software area on developerWorks for technical resources and best practices for Rational Software Delivery Platform products.
  • Explore Rational computer-based, Web-based, and instructor-led online courses. Hone your skills and learn more about Rational tools with these courses, which range from introductory to advanced. The courses on this catalog are available for purchase through computer-based training or Web-based training. Some of the "Getting Started" courses are available free of charge.
  • Subscribe to the IBM developerWorks newsletter, a weekly update on the best of developerWorks tutorials, articles, downloads, community activities, webcasts and events.

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Rational software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational, AIX and UNIX, DevOps
ArticleID=507223
ArticleTitle=How to port from IBM AIX to IBM z/OS
publish-date=08172010