181 Form design: Performance effectsVERSIONS: All, written for Paradox 5
SUBJECT: Performance effects
BY: JOHAN NILSSON and MARK PAUKER
JOHAN NILSSON
One of the major reasons why somebody might NOT want to make applications in Paradox is because of the relatively slow performance of the applications that can be made. One of the best reasons for using it is the quick development time of the applications and the powerful built-in features. If the worst bottlenecks are avoided Paradox is quite a good product...
One of the first things we learn is to use 'delayScreenUpdates(yes)' in certain situations. We learn to hide forms instead of closing them and so on. However, there is so much more we can do. After a while one tends to learn to avoid certain types of solutions and that others are to prefer.
Just to give you an example, I have become increasingly aware of the incredible loss in performance you can expect if you keep many fields outside of a tableframe instead of within the tableframe. I often have for reasons of space on the screen, but now I know I should avoid it if possible.
In the very beginning I was convinced that it was objectPAL's fault Paradox was so slow. Then I discovered that objectPAL could copy more than 50.000 items from an array to another in less than a second on a simple 486. After some time, I started thinking that the bubbling event-model must be the reason for the slow performance. However, I discovered that sometimes speed was slow even when there weren't so many built-in methods triggered in an event-chain. I still think a major bottleneck lies within the event-model. It should be further optimized in compiled forms, going beyond the 'owner' property.
Also, it doesn't take much work in the datamodel before you sink the entire form. It seems that to make data travel from the datamodel to the screen takes a lot of CPU power in Paradox.
MARK PAUKER
Johan,
This is almost opposite to what I had expected, since there is less screen painting to do. Don't ask me why this happens, I only know it does...
I think that what is going on here is that Paradox always redraws in rectangles. When scrolling within a tableFrame, the size of the rectangle that Paradox must redraw is equal to the size of the tableFrame. On the other hand, if you were to place one field from that table in the upper-left corner of the screen, and another in the lower-right corner, then Paradox would need to repaint the entire screen every time you moved to a different record. This can be especially time-consuming if a graph object (or some other object that takes a long time to render) exists somewhere within the rectangle that must be redrawn. My understanding is that even if the value of the field(s) in question don't change, Paradox still redraws them.
BTW, I believe that the performance effect is more pronounced for tall rectangles rather than wide rectangles.
JOHAN NILSSON
Mark,
You have a point here, but I do not think this is what is causing the performance loss. It is my experience that even if the total rectangle size is the same as the size of the tableframe, redrawing is faster with a tableframe only than with a combination of a tableframe and fields outside of it.
To really make sure that what I was saying here was not just my imagination but plain facts I made a simple benchmark test with a table containing one longint field (as key) and fifteen A10 fields. I inserted 1,000 randomly generated records into the table. The key was not randomly generated, but ranged from 1 to 1000.
The benchmark form contained:
1. one tableframe that was 16 fields wide and eight rows high.
2. one tableframe that was 3 fields wide and eight rows high, where the remaining 13 fields were distributed over the screen to make the total area equal to the first tableframe.
The two tableframes where bound to the same table which was included twice in the datamodel.
The benchmark routine:
A simple OPAL routine which stepped through the entire table by repeatedly doing "active.action(DataNextRecord)". The time was measured with "cpuClockTime()".
Stepping through the first tableframe took 107.5 seconds or 0.11 seconds per record.
Stepping through the second tableframe took 660.5 seconds or 0.66 seconds per record.
Thus, I think it is fair to say that one should avoid using the second alternative when not absolutely necessary, since Paradox will behave very slowly.