Performance optimization n RPG program

Performance Optimization for RPG Programs on AS/400

Performance optimization is a critical aspect of RPG programming on the AS/400 platform. When developing RPG programs, it’s important to ensure they run efficiently to maximize system resources and improve the user experience. Whether you’re building an ERP system, a customer relationship management application, or a financial system, ensuring that your RPG programs are optimized for performance to handle large data sets, complex calculations, and other demanding tasks is essential. This post will explore some best practices for optimizing RPG programs on as400 system to achieve peak performance.

Use Appropriate Data Types and Structures

One of the easiest ways to optimize RPG programs on AS/400 is to use appropriate data types and structures. Choosing the smallest data type that can hold the required data is important when defining data structures and variables. Using minimal data types reduces memory usage and improves program performance.

For example, if you only need to store integer values between -32768 and 32767, use the “S” data. Similarly, use the “P” data type for decimal data instead of “S.” Using the appropriate data types significantly reduces memory usage and improves program performance.

Refer to Fig. 1 for an example. 

Use Appropriate Looping Techniques

Looping is an integral part of RPG programming, but it can negatively impact performance if not done correctly. For example, the FOR loop is better suited to looping through large amounts of data than the DO loop. A FOR loop allows the program to anticipate the number of iterations in advance, allowing for better optimization and faster execution by the compiler. On the other hand, a DO loop doesn’t specify the number of iterations in advance, making it less efficient for large data sets since it must check the termination condition for each iteration.

Refer to Fig. 2 for an example. 

Minimize Disk I/O Operations

Using appropriate file access techniques and optimizing database queries is essential to minimize disk I/O operations. For example, to access data from multiple files, use keyed logical files instead of physical files. Keyed logical files provide faster access to data and can significantly reduce disk I/O operations.

 Keyed Logical File (LF)

A keyed logical file is a particular type of file that allows the compiler to find data quickly using a specific key field. This keyed logical file is like an intelligent view of a physical file, optimized to make searching for data based on a specific key fast and efficient.

When a keyed LF is created, the system makes an index of the key field that provides fast data retrieval based on that field. For example, consider a file containing customer data, where the key field is the customer number. If a keyed LF is created based on the customer number field, the system creates an index of that field, which enables fast data retrieval based on the customer number.

Physical File (PF)

Physical files store data records. Initially, the system reads each record sequentially from a physical file until it finds the desired record. When the file is large and contains a lot of data, this can be a slow and resource-intensive process.

Indexing

Similarly, when querying databases, use appropriate indexing techniques to optimize database queries. The proper selection significantly improves query performance and reduces disk I/O operations. The index allows the database to efficiently locate and retrieve the rows that match the query criteria, reducing the need for a full table scan and improving query performance.

Refer to Fig. 3 for an example. 

Use Appropriate Memory Management Techniques

When developing RPG programs, it’s important to use appropriate memory management techniques to ensure optimal performance. For example, use dynamic memory allocation techniques instead of static memory allocation to improve memory usage.

Refer to Fig. 4 for an example. 

Using Subprocedures

One of the most effective ways to optimize performance in RPG programs is to use subprocedures. Subprocedures break up large programs into smaller, more manageable units of code that can be called from other parts of the program. For example, consider an RPG program that calculates the payroll for a large company. Rather than writing all the payroll calculation code in a single program, divide the code into subprocedures, such as one for calculating taxes, one for calculating deductions, and one for calculating benefits. This approach optimizes the performance of the RPG program by reducing the amount of code that needs to be processed at any one time. Additionally, each subprocedure can be called from other parts of the program, making it more modular and easier to maintain.

Refer to Fig. 5 for an example. 

SQL to fetch records

Instead of using traditional file read operations, leverage SQL statements to retrieve the required data efficiently. Avoid using the query Select * from the table if some variables aren’t used. Using SQL to fetch multiple records simultaneously avoids the overhead of individual file read operations, resulting in improved performance when dealing with large datasets. Compile the RPG program and test its performance with substantial data to observe faster execution times compared to the previous version of the program.

Refer to Fig. 6 for an example.

Fig. 1

The EmpId field is packed (6) to hold a six-digit employee ID, while the Salary field is packed (9:2) to hold a salary amount with two decimal places.

The TotalSalary and BonusPercent variables are defined using the smallest data types that can hold the required data.

Fig. 2

Fig. 3

Suppose there is a table called “orders” with four columns listed as “order_id,” “customer_id,” “order_date,” and “total_amount.” You want to retrieve all orders a specific customer makes within a date range.

Without indexing, the SQL query might look like this:

This query would require a full table scan to retrieve the data, which can be slow and resource-intensive, especially if the “orders” table is large.

Create an index on the “customer_id” and “order_date” columns to improve the query’s performance.

With this index in place, the SQL query can now quickly retrieve the relevant data:

Fig. 4

In this example, the program prompts the user to enter the number of elements to store in an array. Instead of statically allocating memory for the display, the program uses the %alloc built-in function to select memory dynamically based on user input.

The program then uses a pointer (ptr) to access the memory and populate the array with values using a loop before the program displays the array’s contents and de-allocates the memory using the %dealloc built-in function.

Example of static memory allocation

This example represents two declared arrays. Array1 allows up to 100 characters, and array2 will have up to 50 packed decimal numbers with two decimal places. A FOR loop initializes each element of array2 with a value that is half of its index. Both arrays are statically allocated, meaning their size is fixed when compiled.

Fig. 5

In this example, the main program calculatePayroll is divided into three smaller subprocedures: calculateGrossPay, calculateNetPay, and updatePayrollFile. Each subprocedure handles a specific part of the payroll calculation process.

Fig. 6