![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
сравнение 2-х TFileStream
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, он провёл сравнение и показал результаты