Using library extensions

Effective use of DLLs could improve the performance of your application if either of the following is true:
  • The application relies on a fetch() or system() function to call programs in other modules.
  • The application is overly large and there are some low-use or special-purpose routines that you can move to a DLL.

If you are using C, consider calling other C modules with fetch() or DLLs instead of system(). A system() call does full environment initialization and termination, but a fetched module and a DLL share the environment of the calling routine. If you are using C++, consider using DLLs.

Use of DLLs requires more overhead than use of statically-bound function calls. You can test your code to determine whether you can afford this extra overhead. First, write the code so that it can be built to implement either a single module or a DLL. Next build your application both ways, and time both applications to see if you can handle the difference in execution time. For best DLL performance, structure the code so that once a function in the DLL is called, it does all it needs to do in the DLL before it returns control to the caller.

You can also choose how to implement DLLs. If you are using C, you can choose between:
  • The XPLINK compiler option
  • The DLL compiler option (which is used with the NOXPLINK option)
    Note: In C++, DLL is not an option, but a default. When you use the XPLINK option, the compiler loads and accesses DLLs faster than it would if you used the DLL option.
The following suggestions could improve the performance of the application:
  • If you are using a particular DLL frequently across multiple address spaces, you can install the DLL in either the LPA/ELPA or the DLPA to avoid load overhead. When the DLL resides in a PDSE, the DLPA services should be used.
  • When you are binding your code, specify both the RENT and the REUSE options. Otherwise, each load of a DLL results in a separately loaded DLL with its own writable static area.
  • Group external variables into one external structure.
  • When you are using z/OS® UNIX, avoid unnecessary load attempts.
    z/OS Language Environment® supports loading a DLL that resides in the UNIX file system or in a data set. However, the location from which it first tries to load the DLL varies, depending whether your application runs with the runtime option POSIX(ON) or POSIX(OFF).
    • If your application runs with POSIX(ON), z/OS Language Environment tries to load the DLL from the UNIX file system first. If you are doing an explicit DLL load using the dllload() function, you can avoid searching the UNIX file system directories. You can direct a DLL search to a data set by prefixing the DLL name with two slashes (//), as follows:
      //MYDLL
    • If your application runs with POSIX(OFF), z/OS Language Environment tries to load your DLL from a data set. Similarly, if you are loading your DLL with the dllload() function and your DLL is loading in UNIX file system, you can avoid the search of the data set by directing a DLL search to the UNIX file system. You can do so by prefixing the DLL name with a period and slash (./), as follows:
      ./mydll
    Note: DLL names are case sensitive in the UNIX file system.
  • When you are using IPA, export only those subprograms (functions and C++ methods) or variables that you need for the interface to the final DLL.

    If you export subprograms or variables unnecessarily (for example, by using the EXPORTALL option), you severely limit IPA optimization. In this case, global variable coalescing and pruning of unreachable or 100% inlined code does not occur. Before it can be processed by IPA, DLLs must contain at least one subprogram. Any attempt to process a data-only DLL will result in a compilation error.

  • The suboption NOCALLBACKANY of the compiler option DLL is more efficient than the CALLBACKANY suboption.
    The CALLBACKANY option calls a Language Environment routine at run time. This runtime service enables a C or C++ NOXPLINK DLL routine to call a C NOXPLINK NODLL routine, which use function pointers that point to actual function entry points rather than function descriptors.
    Note: Compiling source with the DLL option will often cause a degradation in performance when compared against a statically bound application compiled without that option.