Sunday, August 14, 2011

Optimisations

The occupational psychologist (OP) is currently on holiday in USA, so I've had a bit of breathing space. I decided a week ago to try and optimise the use of the management program which I wrote for her; by optimise, I mean to make it work faster and to cut out unnecessary activities.

My first step was to include module logging; I added a table to the database to record which module was used when by whom, and of course added suitable code to each module to record its use, along with a form which displays the total use of each module per time period. The results, even after a few days, were illuminating. As the OP is absent, I was not surprised to see that very few reports were created. What was interesting was to see which data forms were used and how frequently.

It turns out that the most frequently used form - by far - is called EditMeeting. In this form, the user records a meeting for a specific person, choosing values from three different tables in the database along with adding a few dates and a price. My thinking went as follows: as rows are added to those tables infrequently, it might be possible to cache the tables in memory and load them whenever necessary, instead of hitting the database every time the form was loaded. In order to do this, it would be necessary to check first that there had been no change in the tables - meaning that I had to add a new table to the database to record the timestamp of the last change to the tables, and of course, add code to set this timestamp.

Once this had been taken care of, I considered how to cache the data and load. The approach that I took was to define three global clientdatasets in the program's data module, refresh the datasets' contents whenever necessary, and copy their contents to clientdatasets local to the form via cloning their cursors. Part of the information necessary came from this article

When I tested the new version of the program, it appeared to work correctly. I can't really judge whether the program runs faster as I have a complete copy of the database stored on my computer and so my access times are very fast. In the OP's office, the database is stored on a server and so access will naturally be slower. Theoretically, the program can't run any slower than it does now; it can only run faster. But will that improvement be noticeable?

After completing everything, I started thinking about this blog entry, which led me to consider another point which I had previously neglected. EditMeeting is implemented as a modal dialog box which is created every time the user wishes to add a meeting. This means that on every invocation, Delphi (or Windows) has to build the dialog box, load the data and then display the form. It occurs to me that it might be better to create the form once at program startup, using the auto-create function which I always delete, and then simply show and hide the form appropriately. As the form is modal, there is only ever going to be one instance of it visible on the screen at any given time (as opposed to many other forms in the program, which are non-modal). Making this small programming change should also shorten the time which it takes for the form to be displayed on the screen.

Of course, once the form is displayed, time becomes irrelevant as now it is the user who determines how long the form will be displayed on the screen. User time is measured in seconds whereas program time is measured in milliseconds.

The real test will be to sit with someone running the program in order to see what they are doing and why; only on the basis of those observations will I be able to formulate a better way of running the program. Such structural changes are always going to save more time than small optimisations in program code.

No comments: