
In another case, a nightly batch job ran unexpectedly for several hours. Because detailed call stack data had been collected for CPU-intensive jobs, it was possible to see very quickly where the time went. The result was surprisingly clear: about 95% of the runtime was spent on the QUSRJOBI API, used to retrieve file size information.
The mistake was simple. The API call had been placed inside the file-processing loop and was therefore executed alongside each read operation, instead of being called once when the file was opened. Moving that API call outside the loop reduced runtime by 94%. Again, the solution was not difficult once the right data had made the problem visible.
Cases like this are useful because they show how a very large runtime can come from a very small programming choice. From the outside, the batch job looked like a broad performance problem. It consumed many hours and appeared expensive. But the real cause was not spread across the whole program. It was concentrated in one repeated operation.
That is often how application inefficiencies work in practice. A function that seems harmless when executed once can become extremely costly when it runs thousands or millions of times inside the wrong loop. The resulting slowdown may look dramatic, even though the underlying mistake is relatively small.
What made this case easier to explain was not guesswork. It was visibility. Because detailed call stack data had been collected for jobs using significant CPU, it became possible to see where the time was actually going.
That is the important point. If you only know that a job is CPU-intensive, you still do not know why. But if you can see which routines dominate the runtime, the investigation becomes much more direct. In this case, the evidence immediately pointed to the API call instead of forcing people to search through the whole job blindly.
There is another lesson here. The issue was not that QUSRJOBI is a bad API, or that file size information should never be retrieved. The issue was where the call had been placed.
That distinction matters. Performance problems are often not caused by using the wrong tool in general. They are caused by using a reasonable tool in the wrong place, at the wrong frequency, or under the wrong conditions. A call that is perfectly acceptable once per file can become disastrous when executed for every read operation inside a loop.
This is exactly the kind of issue that is hard to spot from source code alone, especially in large or older applications. A developer may not immediately notice that one call is being repeated at a scale that changes the economics of the whole job.
That is why runtime evidence is so valuable. It shows not only what the code is supposed to do, but what it actually costs when it runs in production. In many cases, that is what makes the difference between abstract suspicion and a correction that can be made with confidence.
This case shows that very large performance gains do not always require large rewrites. Sometimes they come from identifying one misplaced operation and moving it to the right place.
But that only happens when the evidence is available. Without the call stack data, the job might simply have remained “slow.” With it, the expensive pattern became visible, the explanation was clear, and the improvement was immediate.
This article is part of GiAPA’s guide: Why IBM i Application Performance Analysis Feels Hard.
If you want the broader context — why IBM i performance problems often seem difficult, what data makes them easier to explain, and how real cases point to practical improvements — the full guide brings the pieces together.