IceCold
IceCold

Reputation: 21231

How to unload a file from cache?

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

Answers (5)

mghie
mghie

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

Zo&#235; Peterson
Zo&#235; Peterson

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

Wim ten Brink
Wim ten Brink

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

Alistair Ward
Alistair Ward

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

Guffa
Guffa

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.

MSDN: CreateFile

Upvotes: 4

Related Questions