2009-06-11 5 views
1

Quelqu'un sait comment décharger un fichier du cache? J'écris un fichier sur le disque, puis je veux le relire. Cependant, Windows me donne le fichier du cache.Comment décharger un fichier du 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; 

- Je suis en train de déterminer la lecture/écriture vitesse d'un lecteur.

+0

Êtes-vous essayer de déterminer combien de temps il faudrait pour lire le morceau?Si tel est le cas, il peut ne pas y avoir de moyen facile d'empêcher la lecture du cache car il s'agit d'un système d'exploitation et éventuellement d'une fonction matérielle (si le disque a une mémoire cache interne). –

+0

@Gerry - Oui, c'est ce que j'essaie de faire. Je pense que le cache de disque (physique) peut être facilement saccagé si j'y lis d'autres fichiers. Donc, cela ne devrait pas être un problème. – Ampere

Répondre

4

code pour démontrer l'utilisation de FILE_FLAG_NO_BUFFERING et de tester la façon dont il affecte votre temps de lecture:

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; 

L'exécution de ce code avec un fichier de 420 taille de mégaoctet donne sur mon système:

temps pour le fichier tampon lu: 3974 de
de temps pour le fichier tampon lu: 0922 de
temps pour le fichier tampon lu: 0937 de
temps pour Buffe fichier rouge lu: 0937 de
Temps pour le fichier tampon lu: 0938 de
Temps pour le fichier unbuffered lu: 3922 de
Temps pour le fichier unbuffered lu: 4000 de
Temps pour le fichier unbuffered lu: 4016 de
de temps pour fichier unbuffered lu: 4062 de
Heure pour le fichier unbuffered lu: 3985 s

+0

MERCI Mghie! Je pense que c'est la réponse dont j'ai besoin. Merci beaucoup! – Ampere

+1

Pourquoi appelez-vous Sleep (0) dans votre code? – Ampere

+0

Eh bien, ça pourrait aussi bien être retiré. Cela n'a pas vraiment d'importance pour le code qui prend des secondes à s'exécuter, mais quand j'ai du code que je veux chronométrer rapidement (n'utilisant pas un profileur externe, mais une unité de profilage que j'utilise) j'insère habituellement un "Sleep (0); " juste avant le début, exécuter le code à profiler dans une tranche de temps complète. Cela compte vraiment si vous voulez comparer l'exécution de plusieurs extraits de code consécutifs, chacun prenant quelques millisecondes. – mghie

4

Je pense que vous avez mal compris le concept de vidage d'un fichier.

Le vidage d'un fichier ne le supprime pas du cache disque, il entraîne l'écriture du contenu du tampon du flux de fichiers dans le fichier.

(Le flux est rincé automatiquement lorsque vous le fermez. L'ouverture d'un fichier et le rinçant sans écrire quoi que ce soit à elle n'a pas d'effet que si jamais.)

Vous pouvez regarder dans le drapeau FILE_FLAG_NO_BUFFERING pour la lecture du fichier, mais il semble de la documentation qu'il n'a aucun effet sur les fichiers sur un disque dur.

MSDN: CreateFile

+0

Le drapeau a également un effet sur les fichiers d'un disque dur, mais il ne peut pas désactiver la mise en mémoire tampon du lecteur de disque lui-même. Ce cache est généralement dans la plage de 2 à 32 Mo sur un lecteur moderne, de sorte que plus le fichier est grand, plus l'influence du cache du lecteur sera faible. – mghie

+0

Mon fichier fait au moins 100 Mo de large. Donc je suppose que Windows cache même des fichiers énormes. – Ampere

+0

Je pense que le cache de disque (physique) peut être facilement saccagé si j'y lis d'autres fichiers. Donc, cela ne devrait pas être un problème. – Ampere

2

la mise en cache de fichiers est une opération de niveau du système d'exploitation, est donc indépendamment du fait que vous utilisez Delphi ou toute autre langue.

Si vous nous donnez une idée de pourquoi vous voulez vous assurer que vous ne lisez pas du cache, il peut être plus facile d'aider.

+0

Certaines personnes (mghie) ont déjà compris pourquoi je veux faire ça :) – Ampere

0

Le code devrait fonctionner, sauf si vous utilisez des valeurs non valides pour la variable Chunk. Par exemple, si le bloc = 0 alors il ne lira aucune donnée dans le tampon, ainsi le tampon conserverait son ancienne valeur. (Ce qui pourrait être les mêmes données que vous venez d'écrire sur le disque.)

+0

No. Chunk est d'environ 100MB. – Ampere

4

Vous devez utiliser l'API Win32 directement, en particulier CreateFile avec l'indicateur FILE_FLAG_NO_BUFFERING. Il oblige le système d'exploitation à lire à partir du disque au lieu du cache et a l'effet secondaire qu'il efface également le cache pour ce fichier, de sorte que la lecture suivante sans le drapeau frappe également le disque, bien qu'il le lise dans le cache puis.

Questions connexes