Many thanks to both NG & the Doc for raising this important side issue of using
DbEngine.Idle dbRefreshCache or
DoEvents.
The main reason I use
DoEvents is for for building in a delay in processing is to allow the display to update progress.
This can be in the form of a progress bar or (in this thread), a message like
'Test 3 ; Loop 4 of 10'.
Doing either is useful for users who know something is happening but it does create a
performance 'hit'. In other words it makes the processing a bit slower.
Like many, some of my regular programming habits are because I've used that method for years without really questioning whether it was the best method.
That's why I like questions like this one as it allows me to check and where necessary update my approach
So far many of my coding habits have (luckily) turned out to be correct in terms of speed e.g.
1. Using Nz rather than Len or Trim to check for empty records - see post
#13
2. Using CurrenDB rather than DBEngine(0)(0) - the focus of this thread
However this thread has raised an issue that I wasn't expecting & will force me to change my habits.
Using
CurrentDB.Execute is slower (sometimes much slower) than setting db as a variable by using
Set db = CurrentDB followed by
db.Execute.
In this thread I had been using DoEvents after each record update building in 10000 pauses.
This was because I originally planned showed messages like:
'Test 3 ; Loop 4 ; Record 352 of 1000'
This caused significant flickering & processing delays so I scrapped the Record part of the message
BUT I forgot to move the DoEvents code from after each record to after each loop
Until now, I've rarely used
DbEngine.Idle dbRefreshCache so I've adapted this test database to do so.
I again used 6 tests to compare the effect of using
1. DoEvents after each record added
2. DoEvents after each loop
3. dbEngine.Idle dbRefreshCache after each record
4. dbEngine.Idle dbRefreshCache after each loop
5. Using the Sleep API to build in a fixed 10 millisecond delay after each loop
6. No delay between events
I used Set db=CurrentDB and db.Execute for each test.
I repeated each test 10 times. Here are the average results:
Results:
Summary:
As you can see using DoEvents after each record creates a significant delay. Unless you need that level of progress detail it is detrimental.
Using Idle dbRefreshCache after each record produces a smaller performance hit (for the reasons explained so clearly by the Doc)
Usng this after each loop is the fastest of all BUT both tests 3 & 4 make the progress indicator erratic - the CPU just doesn't have time to keep up.
As expected, having a fixed delay using Sleep is slow as it means the processor may be paused longer than needed
Perhaps surprisingly, having no delay isn't the fastest method even though I switched off the progress indicator for that test
I also tested this on a laptop ( faster as 8GB RAM) & a tablet (slow - 2GB RAM). The outcomes were the same in each case
Conclusions:
If you want a progress indicator, use DoEvents at appropriate intervals (e.g. after each loop) which allow the display to be updated without a significant performance hit.
If progress displays aren't important, use dbEngine.Idle dbRefreshCache instead ... at suitable intervals. You can always use the hourglass and/or a fixed message 'Updating records....' so the user knows something is happening.
NOTE:
The attached database also includes code to give detailed computer information.
I've done a new thread in the repository to explain that in detail:
Obtain detailed system information