Reputation: 21231
Anybody knows how to unload a file from cache? I write a file to disk, then I want to read it back. However, Windows is giving me the file from cache.
begin
...
{-- Write file --}
AssignFile(F, FileName);
Rewrite(F, 1);
BlockWrite(F, Buf[0], Chunk);
CloseFile(F); { FLUSH }
some code...
then.....
{-- Read file --}
AssignFile(F, FileName);
Reset(F, 1);
BlockRead(F, Buf[0], Chunk); <----------- getting file from cache
CloseFile(F);
end;
- I am trying to determine the write/read speed of a drive.
Upvotes: 1
Views: 1910
Reputation: 32344
Some code to demonstrate the use of FILE_FLAG_NO_BUFFERING
and to test how it affects your reading time:
uses
MMSystem;
function GetTimeForRead(ABuffered: boolean): single;
const
FileToRead = // name of file with maybe 500 MByte size
var
FlagsAndAttributes: DWORD;
FileHandle: THandle;
SrcStream, DestStream: TStream;
Ticks: DWord;
begin
if ABuffered then
FlagsAndAttributes := FILE_ATTRIBUTE_NORMAL
else
FlagsAndAttributes := FILE_FLAG_NO_BUFFERING;
FileHandle := CreateFile(FileToRead, GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, FlagsAndAttributes, 0);
if FileHandle = INVALID_HANDLE_VALUE then begin
Result := 0.0;
exit;
end;
SrcStream := THandleStream.Create(FileHandle);
try
DestStream := TMemoryStream.Create;
try
DestStream.Size := SrcStream.Size;
Sleep(0);
Ticks := timeGetTime;
DestStream.CopyFrom(SrcStream, SrcStream.Size);
Result := 0.001 * (timeGetTime - Ticks);
finally
DestStream.Free;
end;
finally
SrcStream.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
Button1.Enabled := FALSE;
try
Update;
Memo1.Lines.Clear;
for i := 1 to 5 do begin
Memo1.Lines.Add(Format('Time for buffered file read: %.3f s',
[GetTimeForRead(TRUE)]));
end;
for i := 1 to 5 do begin
Memo1.Lines.Add(Format('Time for unbuffered file read: %.3f s',
[GetTimeForRead(FALSE)]));
end;
finally
Button1.Enabled := TRUE;
end;
end;
Running this code with a file of 420 MByte size gives on my system:
Time for buffered file read: 3,974 s
Time for buffered file read: 0,922 s
Time for buffered file read: 0,937 s
Time for buffered file read: 0,937 s
Time for buffered file read: 0,938 s
Time for unbuffered file read: 3,922 s
Time for unbuffered file read: 4,000 s
Time for unbuffered file read: 4,016 s
Time for unbuffered file read: 4,062 s
Time for unbuffered file read: 3,985 s
Upvotes: 4
Reputation: 13332
You'll need to use the Win32 API directly, specifically CreateFile with the FILE_FLAG_NO_BUFFERING flag. It forces the OS to read from the disk instead of the cache, and has the side effect that it also clears out the cache for that file, so the next read without the flag also hits the disk, though it does read it into the cache then.
Upvotes: 4
Reputation: 26682
The code should be fine, unless you're using invalid values for the Chunk variable. E.g., if chunk = 0 then it won't read any data into the buffer, thus the buffer would keep it's old value. (Which could be the same data you just wrote to disk.)
Upvotes: 0
Reputation: 1093
File caching is an OS level operation, so is independent of whether you use Delphi or any other language.
If you give us some idea of why you want to ensure you are not reading from cache, it may be easier to help.
Upvotes: 2
Reputation: 700840
I think that you have misunderstood the concept of flushing a file.
Flushing a file does not remove it from the disk cache, it causes the content of the file stream's buffer to be written to the file.
(The stream is automatically flushed when you close it. Opening a file and flushing it without writing anything to it has no effect what so ever.)
You can look into the FILE_FLAG_NO_BUFFERING
flag for reading the file, but it seems from the documentation that it has no effect on files on a hard drive.
Upvotes: 4