2009-06-11 4 views
1

누구나 캐시에서 파일을 언로드하는 방법을 알고 있습니까? 디스크에 파일을 쓰고 다시 읽으려고합니다. 그러나 Windows 캐시에서 파일을 제공하고 있습니다.캐시에서 파일을 언로드하는 방법은 무엇입니까?

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; 

- 나는/쓰기를 결정 드라이브의 읽기 속도하려합니다.

+0

것은 당신이 청크를 읽는 데 걸리는 시간을 결정하려고합니까?그렇다면 운영 체제 및 가능한 하드웨어 (디스크에 내부 캐시가있는 경우) 기능이므로 캐시에서 읽기를 방지하는 쉬운 방법이 없을 수 있습니다. –

+0

@Gerry - 예, 이것이 내가하려는 일입니다. 나는 (물리적 인) 디스크 캐시가 다른 파일을 읽으면 쉽게 파기 할 수 있다고 생각한다. 그래서 이것은 문제가되어서는 안됩니다. – Ampere

답변

4

일부 코드 FILE_FLAG_NO_BUFFERING의 사용을 설명하고 그것이 당신의 독서 시간에 미치는 영향을 테스트 :

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; 

내 시스템이 420 메가 바이트 크기의 파일에 코드를 제공합니다 실행 :

을 버퍼링 된 파일 읽기 시간 : 3,974 초
버퍼링 된 파일 읽기 시간 : 0,922 초
버퍼 파일 읽기 시간 : 0,937 초
버퍼링 시간 빨간색 파일 읽기 : 0937의
시간 버퍼 파일 읽기 : 0938의
시간 버퍼되지 않은 파일 읽기 : 3922의
시간 버퍼되지 않은 파일 읽기 : 4,000의
시간 버퍼되지 않은 파일 읽기 : 4016의
시간을 위해 버퍼링 파일 읽기 : 버퍼링 파일 4062의
시간 읽기 : 3985 S가

+0

고맙습니다. 이것이 내가 필요한 대답이라고 생각합니다. 감사합니다. – Ampere

+1

코드에서 Sleep (0)을 호출하는 이유는 무엇입니까? – Ampere

+0

음, 제거 할 수도 있습니다. 실행하는 데 몇 초가 걸리는 코드에는 별 문제가되지 않지만, 빠르게 (외부 프로파일 러를 사용하지 않고 필자가 사용하는 프로파일 링 유닛을 사용하지 않고) 코드를 작성할 때 "습관 (0); " 시작 직전에 완전한 타임 슬라이스 내에서 프로파일 링 될 코드를 실행합니다. 몇 밀리 초가 걸리는 연속적인 코드 스 니펫의 런타임을 비교하려면 확실히 중요합니다. – mghie

4

파일 플러시의 개념을 잘못 이해했다고 생각합니다.

파일을 플러시해도 디스크 캐시에서 제거되지 않으면 파일 스트림의 버퍼 내용이 파일에 기록됩니다.

(당신이 그것을 닫을 때 스트림이 자동으로 플러시됩니다. 파일을 열기하고 어떤 일이든 아무런 영향을 미치지 않습니다에 아무것도 작성하지 않고 그것을 세척.)

파일을 읽기 위해 FILE_FLAG_NO_BUFFERING 플래그로 볼 수

, 하지만 하드 드라이브의 파일에는 아무런 영향을 미치지 않는다는 것이 설명서에서 밝혀졌습니다.

MSDN: CreateFile

+0

플래그는 하드 드라이브의 파일에도 적용되지만 디스크 드라이브 자체의 버퍼링을 비활성화 할 수는 없습니다. 이 캐시는 일반적으로 현대 드라이브의 경우 2 - 32MByte이므로 파일이 클수록 드라이브 캐시의 영향이 적습니다. – mghie

+0

내 파일 크기는 100MB 이상입니다. 그래서 나는 Windows가 거대한 파일을 캐싱하고 있다고 생각합니다. – Ampere

+0

(물리적 인) 디스크 캐시는 다른 파일을 읽으면 쉽게 파기 될 수 있다고 생각합니다. 그래서 이것은 문제가되어서는 안됩니다. – Ampere

2

파일 캐싱 그래서 당신은 델파이 또는 다른 언어를 사용하는지 여부와 상관없이, 운영체제 수준의 작업입니다.

의 이유를 알려 주시면 캐시를 읽지 않으려는 이유가 일 때 도움이 될 수 있습니다.

+0

일부 사람들 (mghie)은 이미 내가 왜 이것을하고 싶은지를 알아 냈습니다. – Ampere

0

청크 변수에 유효하지 않은 값을 사용하지 않는 한 코드가 잘되어야합니다. 예를 들어 chunk = 0이면 버퍼에 데이터를 읽지 않으므로 버퍼가 이전 값을 유지합니다. (디스크에 쓴 것과 동일한 데이터 일 수 있습니다.)

+0

아니요. 청크는 약 100MB입니다. – Ampere

4

Win32 API를 직접 사용해야합니다. 특히 CreateFile을 FILE_FLAG_NO_BUFFERING 플래그와 함께 사용해야합니다. OS가 캐시 대신 디스크에서 강제로 읽도록하고, 그 파일에 대한 캐시를 지우는 부작용이 있습니다. 따라서 플래그가없는 다음 읽기도 캐시로 읽지 만 디스크를 치게됩니다 그때.

관련 문제