In a couple of threads lately the filecache has gotten in the way of making reliable timings of code snippets under test.
Whatever size of filecache we have, writing a sufficiently large file will only purge the head of the file, the tail will remain in the file cache. Random access will probably see some hits and affect the timings.
One way to ensure that the file, or part of a file, is not in the filecache is to restart the system before another trial. A pain if ever there was one. We now have another way.
During one of the aforementioned threads I was playing around with a Createfile/Readfile combo in a working app and noticed that on running another routine a particular file, which had been read previously by that routine, came in as if read for the first time; that is read from the hard drive and not the filecache. On another read it came in very quickly, as expected. However, when I ran the Createfile/Readfile combo again and followed by running the other routine again the file came in, again, as if read for the first time.
The Createfile implemented the FILE_FLAG_NO_BUFFERING flag which effectively allows a file to come in, and out, without being buffered. It also seems that if any part or all of a particular file coming in that way is in the filecache it gets purged. This is clearly by design but I have yet to find any evidence to support this. Paul Purvis also spotted this behaviour and suggested I put something in the Source Code forum. I didn't but after the most recent thread I thought I've give it a closer look as I was getting fed up of rebooting and I now reckon that it is worth a mention.
I also reckon that some, if not many, of you may have also spotted this behaviour but didn't think it had any value.
Anyway, lets try it.
If the following code is run as is, a 100MB file is written to the root of C: and then read twice. The file is cached on writing so the two reads are completed quite quickly, 0.20s and 0.17s on my machine. If you have a small filecache then try a 50MB file or whatever - the point being all of the file should be accommodated by the filecache.
If the first ClearFileCache is uncommented and the app run again I get 2.26s and 0.19s. The file is purged from the filecache before the first read but gets cached on that read so 'belts' through on the second read.
If we uncomment the second ClearFileCache and run again I get 2.30s and 2.75s. That is, neither read gets the benefit of caching.
At this point the file is still in the filecache so if we now comment the first ClearFileCache and run again I get 0.19s and 2.23s, the second read is now being derived of caching.
So far so good.
I don't persuade easy so I rebooted and simply read the file. The filecache hadn't seen the file yet and it came in at 2.24s.
So, there you have it. If you want to time test some 'input/number crunching' routines and want to avoid the agony of rebooting every flaming time give this a whirl.
Added: A 2 crept into the code somehow. Conclusions are the same - the timings above have been changed to accommodate the correction of code.
Ignore the following listing. The idea is OK but it is poorly implemented. I should remove it but I'll not hide from the fact that it is flawed.
Go straight to ClearFileCache2 - I'm close to being happy with that. We're never really happy are we?
Whatever size of filecache we have, writing a sufficiently large file will only purge the head of the file, the tail will remain in the file cache. Random access will probably see some hits and affect the timings.
One way to ensure that the file, or part of a file, is not in the filecache is to restart the system before another trial. A pain if ever there was one. We now have another way.
During one of the aforementioned threads I was playing around with a Createfile/Readfile combo in a working app and noticed that on running another routine a particular file, which had been read previously by that routine, came in as if read for the first time; that is read from the hard drive and not the filecache. On another read it came in very quickly, as expected. However, when I ran the Createfile/Readfile combo again and followed by running the other routine again the file came in, again, as if read for the first time.
The Createfile implemented the FILE_FLAG_NO_BUFFERING flag which effectively allows a file to come in, and out, without being buffered. It also seems that if any part or all of a particular file coming in that way is in the filecache it gets purged. This is clearly by design but I have yet to find any evidence to support this. Paul Purvis also spotted this behaviour and suggested I put something in the Source Code forum. I didn't but after the most recent thread I thought I've give it a closer look as I was getting fed up of rebooting and I now reckon that it is worth a mention.
I also reckon that some, if not many, of you may have also spotted this behaviour but didn't think it had any value.
Anyway, lets try it.
If the following code is run as is, a 100MB file is written to the root of C: and then read twice. The file is cached on writing so the two reads are completed quite quickly, 0.20s and 0.17s on my machine. If you have a small filecache then try a 50MB file or whatever - the point being all of the file should be accommodated by the filecache.
If the first ClearFileCache is uncommented and the app run again I get 2.26s and 0.19s. The file is purged from the filecache before the first read but gets cached on that read so 'belts' through on the second read.
If we uncomment the second ClearFileCache and run again I get 2.30s and 2.75s. That is, neither read gets the benefit of caching.
At this point the file is still in the filecache so if we now comment the first ClearFileCache and run again I get 0.19s and 2.23s, the second read is now being derived of caching.
So far so good.
I don't persuade easy so I rebooted and simply read the file. The filecache hadn't seen the file yet and it came in at 2.24s.
So, there you have it. If you want to time test some 'input/number crunching' routines and want to avoid the agony of rebooting every flaming time give this a whirl.

Added: A 2 crept into the code somehow. Conclusions are the same - the timings above have been changed to accommodate the correction of code.
Ignore the following listing. The idea is OK but it is poorly implemented. I should remove it but I'll not hide from the fact that it is flawed.
Go straight to ClearFileCache2 - I'm close to being happy with that. We're never really happy are we?

Code:
#Compile Exe ' 8.04 #Register None #DIM ALL #TOOLS OFF %NOMMIDS = 1 %NOGDI = 1 #Include "WIN32API.inc" ' 1 November 2006 $sFile = "c:\test" Sub ClearFileCache(sFile As String , Buffer As String) Local hFile, Chunk, nbLoaded As Long, ptrBuffer As Dword Ptr Dim zFile As Asciiz * 256 zFile = sFile hFile = CreateFile(zFile, %GENERIC_READ, 0, ByVal 0, %OPEN_EXISTING, %FILE_FLAG_SEQUENTIAL_SCAN Or %FILE_FLAG_NO_BUFFERING, ByVal 0) Chunk = Len(Buffer) ptrBuffer = StrPtr(Buffer) Do ReadFile( hFile, ByVal ptrBuffer, ByVal Chunk, nbLoaded, ByVal 0 ) Loop Until nbLoaded = 0 CloseHandle(hFile) End Sub Function PBMain( ) As Long Dim strNull As String Local i As Long, t1, t2 As Ext strNull = Nul$(1048576) ' 1 MB If Dir$($SFile) = "" Then ' Write a 100MB file Open $sFile For Binary As #1 For i = 1 To 100 Put$ #1, strNull Next Close #1 End If ' Clear filecache after creation, if done, and before before first read 'ClearFileCache($sFile, strNull) ' Read file t1 = Timer t1 = Timer Open $sFile For Binary As #1 For i = 1 To 100 Get$ #1, 10[COLOR="Red"]2[/COLOR]48576, strNull ' Remove the [COLOR="Red"]2[/COLOR] Next Close #1 t1 = Timer - t1 ' Clear filecache after first reading and before second read 'ClearFileCache($sFile, strNull) ' Read file again t2 = Timer Open $sFile For Binary As #1 For i = 1 To 100 Get$ #1, 10[COLOR="Red"]2[/COLOR]48576, strNull ' Remove the [COLOR="Red"]2[/COLOR] Next Close #1 t2 = Timer - t2 MsgBox Using$("##.##",t1) + " " + Using$("##.##",t2) END FUNCTION
Comment