Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

сравнение 2-х TFileStream


Страницы:   1 2 3 4 5

Unknown1 ©   (2012-11-16 11:16:00) 

Как быстро сравнить?


Anatoly Podgoretsky   (2012-11-27 20:29:00) [1]

> DVM  (27.11.2012 17:53:20)  [80]

Теперь я понял твою мысль


QAZ9   (2012-11-27 18:29:00) [2]

Удалено модератором


DVM   (2012-11-27 17:53:00) [3]


> anatoly pogoretsky   (27.11.12 17:42) [78]
> > DVM  (27.11.2012 16:35:17)  [77]
>
> Ты не пугай
>


> Ограничение на размер файла 2^64, просто работать придется
> кусками, виртуальное пространство не ограничивает.

Ну ограничение на самом деле на порядки меньшее число, но не в этом суть.

Очевидно, что проецируя кусками можно сравнить два файла любого размера, я ж говорил про проецирование целиком.


anatoly podgoretsky   (2012-11-27 17:45:00) [4]

LPVOID WINAPI MapViewOfFile(
 _In_  HANDLE hFileMappingObject,
 _In_  DWORD dwDesiredAccess,
 _In_  DWORD dwFileOffsetHigh,
 _In_  DWORD dwFileOffsetLow,
 _In_  SIZE_T dwNumberOfBytesToMap
);

Ограничение на размер файла 2^64, просто работать придется кусками, виртуальное пространство не ограничивает.


anatoly pogoretsky   (2012-11-27 17:42:00) [5]

> DVM  (27.11.2012 16:35:17)  [77]

Ты не пугай

HANDLE WINAPI CreateFileMapping(
 _In_      HANDLE hFile,
 _In_opt_  LPSECURITY_ATTRIBUTES lpAttributes,
 _In_      DWORD flProtect,
 _In_      DWORD dwMaximumSizeHigh,
 _In_      DWORD dwMaximumSizeLow,
 _In_opt_  LPCTSTR lpName
);


DVM   (2012-11-27 16:35:00) [6]


> DevilDevil ©   (27.11.12 14:11) [75]


> я говорю как с помощью Mapped сравнить 2 файла размером
> 2гб ?

В 32 бит никак. Не хватит виртуального адресного пространства.
В 64 бит все нормально сравнивается. Собственно я и сравнивал примерно такие файлы.


>  на сколько затратно по ОЗУ

Смотря что понимать под ОЗУ. Если виртуальное адресное пространство, то его израсходуется около 4 гб, реального физического же совсем мало.


brother   (2012-11-27 14:32:00) [7]

> при чтении с хардов 256 Кб

с чего бы?


DevilDevil   (2012-11-27 14:11:00) [8]

>  DVM ©   (27.11.12 11:43) [73]

я говорю как с помощью Mapped сравнить 2 файла размером 2гб ?
эффективно ли это будет, на сколько затратно по ОЗУ


QAZ9   (2012-11-27 11:48:00) [9]

наилучший по скорости чтения размер буфера при чтении с хардов 256 Кб


DVM   (2012-11-27 11:43:00) [10]


> DevilDevil ©   (27.11.12 00:25) [72]


> а если по 2 гб ?

Буфер на 2 Гб? Это в 32 бит системе еще надо постараться распределить. Речь о вот этом же временном буфере то, а не о всем файле:

class function TStreamHelper.CompareStreams(A, B: TStream;
BufferSize: Integer = DefStreamBufferSize): Boolean;
var
BufferA, BufferB: array of Byte;
ByteCountA, ByteCountB: Longint;
begin
SetLength(BufferA, BufferSize);          // <<= этот буфер
try
  SetLength(BufferB, BufferSize);         // <<= и этот
  try
    repeat
      ByteCountA := A.Read(BufferA[0], BufferSize);
      ByteCountB := B.Read(BufferB[0], BufferSize);

      Result := (ByteCountA = ByteCountB);
      Result := Result and CompareMem(BufferA, BufferB, ByteCountA);
    until (ByteCountA <> BufferSize) or (ByteCountB <> BufferSize) or not Result;
  finally
    SetLength(BufferB, 0);
  end;
finally
  SetLength(BufferA, 0);
end;
end;


DevilDevil   (2012-11-27 00:25:00) [11]

> При размере буфера 64к скорости сравнялись. До 64к сравнение
> отображенных в память было быстрее, чем по блокам.


а если по 2 гб ?


bems   (2012-11-19 15:04:00) [12]


> ага, интересно, значит у меня отфонарно, а ты у нас исключительно
> утверждаеш :) даже не проводя тест
> и какой такой размер "правильный" , он в MMF вообще не задается
> :)
размер задаётся при ручном чтении, и когда он правильный достигает быстродействия MMF
Ну конечно число у тебя отфонарное. Хотя бы потому что тебе уже показали что размер реальной оперативы не влияет на MMF (вернее влияет, но не более чем и на ручное чтение).
Про то что 4 гигабайта это и для физической оперативы средняя температура по больнице.
Короч хватит, вывод из обсуждения уже давно очевиден, а ты всё трепыхаешься


QAZ9   (2012-11-19 12:18:00) [13]

так не интересно :( надо готовый проект в архивчике


DVM   (2012-11-19 11:29:00) [14]

Сам код тестирования я не сохранял, там кода то 5 строчек.

Кому обертки не нравятся я не настаиваю.


DVM   (2012-11-19 11:24:00) [15]

Код для сравнения с помощью буфера выше. Соответственно нужен код, для маппинга файлов. Я использовал опять же свою обертку для MMF в виде TStream:


////////////////////////////////////////////////////////////////////////////////
// TCustomMappedStream
////////////////////////////////////////////////////////////////////////////////

 TCustomMappedStream = class(TStream)
 private
   FMapHandle: THandle;
   FFileHandle: THandle;
   FReadOnly: Boolean;
   FMemory: Pointer;
   FPosition, FSize: Int64;
 protected
   function CreateMapView(APageSize: Int64; AName: PChar = nil): Int64;
   procedure CloseMapView;
 public
   function Read(var Buffer; Count: Longint): Longint; override;
   function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
   property Memory: Pointer read FMemory;
   property MapHandle: THandle read FMapHandle;
   property FileHandle: THandle read FFileHandle;
   property ReadOnly: Boolean read FReadOnly;
 end;

////////////////////////////////////////////////////////////////////////////////
// TFileMappedStream
////////////////////////////////////////////////////////////////////////////////

 TFileMappedStream = class(TCustomMappedStream)
 private
   FFilename: String;
 protected
   procedure SetSize(NewSize: Longint); overload; override;
   procedure SetSize(const NewSize: Int64); overload; override;
 public
   constructor Create(const Filename: String; Mode: Word);
   destructor Destroy; override;
   function Write(const Buffer; Count: Longint): Longint; override;
   procedure Clear;
 end;

resourcestring

 rsNoDataAvailable = 'No data available.';
 rsCannotAccessMemoryData = 'Cannot access memory data.';
 
.....
 
////////////////////////////////////////////////////////////////////////////////
// TCustomMappedStream
////////////////////////////////////////////////////////////////////////////////

function TCustomMappedStream.CreateMapView(APageSize: Int64; AName: PChar = nil): Int64;
var
 Inf: TMemoryBasicInformation;
begin
 if APageSize = 0 then
   APageSize := 1;
 if not Readonly then
   FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READWRITE, 0, APageSize, AName)
 else
   FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READONLY, 0, APageSize, AName);
 Win32Check(FMapHandle <> 0);

 if not FReadOnly then
   FMemory := MapViewOfFile(FMapHandle, FILE_MAP_READ or FILE_MAP_WRITE, 0, 0, 0)
 else
   FMemory := MapViewOfFile(FMapHandle, FILE_MAP_READ, 0, 0, 0);

 if (Assigned(FMemory)) and (AName = nil) then
   Result := APageSize
 else
   if (Assigned(FMemory)) and (Assigned(AName)) then
     begin
       VirtualQuery(FMemory,inf,SizeOf(TMemoryBasicInformation));
       Result := inf.RegionSize;
     end
   else
     raise EStreamError.Create(SysErrorMessage(GetLastError));
end;

//------------------------------------------------------------------------------

procedure TCustomMappedStream.CloseMapView;
begin
 if Memory <> nil then
   UnmapViewOfFile(Memory);
 if FMapHandle <> 0 then
   CloseHandle(FMapHandle);
end;

//------------------------------------------------------------------------------

function TCustomMappedStream.Read(var Buffer; Count: Integer): Longint;
begin
 if FMemory <> nil then
   begin
     if FPosition + Count > Size then
       Count := FSize - FPosition;
     Move(Pointer(PtrInt(FMemory) + FPosition)^, Buffer, Count);
     Inc(FPosition, Count);
     Result := Count;
   end
 else
   raise EStreamError.Create(rsNoDataAvailable);
end;

//------------------------------------------------------------------------------

function TCustomMappedStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
begin
 case Origin of
   soBeginning: FPosition := Offset;
   soCurrent  : FPosition := FPosition + Offset;
   soEnd      : FPosition := FSize + Offset;
 end;
 Result := FPosition;
end;

////////////////////////////////////////////////////////////////////////////////
// TFileMappedStream
////////////////////////////////////////////////////////////////////////////////

constructor TFileMappedStream.Create(const Filename: String; Mode: Word);
const
 Access: array[0..4] of Cardinal = (GENERIC_READ, GENERIC_WRITE,
                                    GENERIC_READ or GENERIC_WRITE,
                                    GENERIC_READ or GENERIC_WRITE,
                                    GENERIC_READ or GENERIC_WRITE);
 CreateFlag: array[0..4] of Cardinal = (OPEN_EXISTING, OPEN_EXISTING,
                                        OPEN_EXISTING, CREATE_ALWAYS,
                                        CREATE_ALWAYS);
var
 FileFlag: Cardinal;
begin
 inherited Create;
 FFilename := Filename;
 FReadOnly := Mode = 0;
 if Mode = fmCreate then
   Mode := 3;
 if Mode <> 4 then
   FileFlag := FILE_ATTRIBUTE_NORMAL
 else
   FileFlag := FILE_FLAG_DELETE_ON_CLOSE;
 FFileHandle := CreateFile(PChar(FFilename), Access[Mode], 0, nil, CreateFlag[Mode], FileFlag, 0);
 Win32Check(FFileHandle <> INVALID_HANDLE_VALUE);
 FSize := CreateMapView(GetFileSize(FFileHandle, nil));
end;

//------------------------------------------------------------------------------

procedure TFileMappedStream.SetSize(NewSize: Integer);
begin
 SetSize(Int64(NewSize));
end;

//------------------------------------------------------------------------------

procedure TFileMappedStream.SetSize(const NewSize: Int64);
begin
 CloseMapView;
 SetFilePointer(FFileHandle, NewSize, nil, FILE_BEGIN);
 SetEndOfFile(FFileHandle);
 FSize := CreateMapView(NewSize);
end;

//------------------------------------------------------------------------------

destructor TFileMappedStream.Destroy;
begin
 CloseMapView;
 CloseHandle(FFileHandle);
 inherited Destroy;
end;

//------------------------------------------------------------------------------

function TFileMappedStream.Write(const Buffer; Count: Integer): Longint;
begin
 if (FMemory <> nil) and (not Readonly) then
   begin
     if (FPosition + Count > FSize) then
       SetSize(FPosition+Count);
     Move(Buffer,Pointer(PtrInt(FMemory) + FPosition)^,Count);
     inc(FPosition,Count);
     Result := Count;
   end
 else
   raise EStreamError.Create(rsCannotAccessMemoryData);
end;

//------------------------------------------------------------------------------

procedure TFileMappedStream.Clear;
begin
 SetSize(0);
 FPosition := 0;
end;


DVM   (2012-11-19 11:22:00) [16]


> QAZ9   (19.11.12 11:18) [66]


> DVM давай код теста и параметры окружающей среды :)

Все тебе дай, сам бы давно написал.


QAZ9   (2012-11-19 11:18:00) [17]


> моё утверждение основывается на том, что в обоих случаях
> одинаковое количество чтений с диска (при правильном размере
> буффера).

ага, интересно, значит у меня отфонарно, а ты у нас исключительно утверждаеш :) даже не проводя тест
и какой такой размер "правильный" , он в MMF вообще не задается :)

DVM давай код теста и параметры окружающей среды :)


DVM   (2012-11-19 11:07:00) [18]


> Unknown1   (19.11.12 10:35) [64]


> А зачем здесь  SetLength(BufferB, 0); и SetLength(BufferA,
>  0);?

Привык убирать за собой.

Иногда бывает полезно даже для автоматически освобождаемых типов как например строки это делать. Если, например строка объявлена как threadvar S: string, то не выполнив для нее SetLength(S, 0); мы в конце получим утечку, о которой FastMem нам радостно сообщит.


Unknown1   (2012-11-19 10:35:00) [19]


> DVM ©   (16.11.12 15:09) [12]
>
> class function TStreamHelper.CompareStreams(A, B: TStream;
>
>  BufferSize: Integer = DefStreamBufferSize): Boolean;
> var
>  BufferA, BufferB: array of Byte;
>  ByteCountA, ByteCountB: Longint;
> begin
>  SetLength(BufferA, BufferSize);
>  try
>    SetLength(BufferB, BufferSize);
>    try
>      repeat
>        ByteCountA := A.Read(BufferA[0], BufferSize);
>        ByteCountB := B.Read(BufferB[0], BufferSize);
>
>        Result := (ByteCountA = ByteCountB);
>        Result := Result and CompareMem(BufferA, BufferB,
>  ByteCountA);
>      until (ByteCountA <> BufferSize) or (ByteCountB <>
> BufferSize) or not Result;
>    finally
>      SetLength(BufferB, 0);
>    end;
>  finally
>    SetLength(BufferA, 0);
>  end;
> end;
>
>


А зачем здесь   SetLength(BufferB, 0);и SetLength(BufferA, 0);?


bems   (2012-11-19 03:54:00) [20]


> это объем озу на котором стоит бо'льшая часть х64 ОСей на
> данный момент, всего лиш...
это отфонарное значение, которое ты сказал неподумав

> у раз пошла такая пьянка давай код сравнения скорости ,проверим
моё утверждение основывается на том, что в обоих случаях одинаковое количество чтений с диска (при правильном размере буффера).
За кодом к DVM, он провёл сравнение и показал результаты


Страницы:   1 2 3 4 5

Наверх

Титульная страница Поиск, карта сайта Написать письмо