Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.07.21;
Скачать: [xml.tar.bz2];

Вниз

сравнение 2-х TFileStream   Найти похожие ветки 

 
Unknown1   (2012-11-16 11:16) [0]

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


 
RWolf ©   (2012-11-16 11:21) [1]

сравнить размеры, при совпадении прочитать данные поблочно да сравнить, а как ещё-то? потоки ничего больше не умеют, только читать и писать.


 
Unknown1   (2012-11-16 11:34) [2]


> сравнить размеры, при совпадении прочитать данные поблочно
> да сравнить, а как ещё-то? потоки ничего больше не умеют,
>  только читать и писать.


Так вот:


function FilesAreEqual(const FileName1, FileName2: string): Boolean;
const
 BLOCK_SIZE = 65536;
var
 Buf1, Buf2: array[1..BLOCK_SIZE] of Byte;
 FS1, FS2: TFileStream;
 Len1, Len2: Integer;
begin
 Result := False;
 FS1 := TFileStream.Create(FileName1, fmOpenRead or fmShareDenyNone);
 try
   FS2 := TFileStream.Create(FileName2, fmOpenRead or fmShareDenyNone);
   try
     if FS1.Size <> FS2.Size then
       Exit;
     Len1 := FS1.Read(Buf1[1], BLOCK_SIZE);
     Len2 := FS2.Read(Buf2[1], BLOCK_SIZE);
     if Len1 <> Len2 then
       Exit;
     if not CompareMem(@Buf1[1], @Buf2[1], Len1) then
       Exit;
     Result := True;
   finally
     FS2.Free;
   end;
 finally
   FS1.Free;
 end;
end;


 
AV ©   (2012-11-16 11:46) [3]

это первые 65536 байт только


 
Amoeba_   (2012-11-16 11:51) [4]


>  при совпадении прочитать данные поблочно да сравнить, а
> как ещё-то?

Можно и иначе, без TFileStream и без поблочного чтения. Отображаешь файлы (memory mapping, используются ф-и API) в память, и как для двух массивов байтов делаешь CompareMem.


 
RWolf ©   (2012-11-16 11:53) [5]


> Amoeba_   (16.11.12 11:51) [4]

можно, но условием задачи было сравнение 2-х TFileStream.


 
Dimka Maslov ©   (2012-11-16 12:00) [6]

MD5 высчитать для обоих файлов.


 
QAZ9   (2012-11-16 12:50) [7]


> Можно и иначе

можно, но ненужно, ибо будут проблемы как со скоростью, так и с размером файлов


 
bems ©   (2012-11-16 13:26) [8]

С размером только на х32
А какие тут проблемы со скоростью?


 
RWolf ©   (2012-11-16 13:41) [9]

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


 
Игорь Шевченко ©   (2012-11-16 13:52) [10]

RWolf ©   (16.11.12 13:41) [9]

Не выигрывает


 
AV ©   (2012-11-16 15:01) [11]


> Игорь Шевченко ©   (16.11.12 13:52) [10]

почему?

Если файл большой, система скажет, что готово, отображено все. А потом, за кулисами, будет лазить в файл.

против

Зачитать в память все. Если не сбросит в своп - все в память.


 
DVM ©   (2012-11-16 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;


 
DVM ©   (2012-11-16 15:11) [13]


> Можно и иначе, без TFileStream и без поблочного чтения.
> Отображаешь файлы (memory mapping, используются ф-и API)
> в память

Не все можно отобразить в память. Адресное пространстов 32 бит программ невелико по меркам современных жестких дисков и например два видеофайла туда не отобразить больших.


 
Игорь Шевченко ©   (2012-11-16 15:11) [14]


> почему?


почитай как Windows работает с файлами


 
DVM ©   (2012-11-16 15:14) [15]

С чего вдруг сравнение двух файлов отображенных в память будет выигрывать у сравнения двух файлов методом поблочного чтения? При отображении все равно будет такое же чтение с диска такими же блоками, волшебства тут не будет.


 
DVM ©   (2012-11-16 15:14) [16]


> Игорь Шевченко ©   (16.11.12 15:11) [14]

Чтоб сравнить все равно потребуется чтение с диска, как б она с ним не работала.


 
Игорь Шевченко ©   (2012-11-16 15:26) [17]

DVM ©   (16.11.12 15:14) [16]

Почитай, как Windows работает с файлами. Первым делом при чтении в кэш она их отображает в память нужными определенными порциями.


 
DVM ©   (2012-11-16 15:31) [18]


> Игорь Шевченко ©   (16.11.12 15:26) [17]


> Первым делом при чтении в кэш она их отображает в память
> нужными определенными порциями.

Если я буду читать такими же примерно порциями? Сомневаюсь, что будет сильный выигрыш.

Легко поставить эксперимент, кстати. Сейчас проверю.


 
RWolf ©   (2012-11-16 15:33) [19]


> Игорь Шевченко ©   (16.11.12 15:26) [17]

читать в буфер можно ведь и мимо кэша, не?


 
DVM ©   (2012-11-16 15:42) [20]

Сравнил я.
При размере буфера 64к скорости сравнялись. До 64к сравнение отображенных в память было быстрее, чем по блокам. Но тут надо учитывать, что сравнивать все равно придет поблочно читая из отображенных в память файлов, т.к. натравливать на них CompareMem не очень практично, т.к. при больших файлах этот процесс нельзя будет прервать и в реальной жизни так не удобно.


 
DVM ©   (2012-11-16 15:45) [21]

Если отображенные в память файлы сравнивать просто CompareMem, то немного быстрее поблочного чтения, примерно на 25%.


 
Игорь Шевченко ©   (2012-11-16 15:48) [22]

RWolf ©   (16.11.12 15:33) [19]


> читать в буфер можно ведь и мимо кэша, не?


Можно. Но надо исхитряться. По умолчанию работа с файлами выполняется с использованием кэша.


 
Игорь Шевченко ©   (2012-11-16 15:50) [23]

DVM ©   (16.11.12 15:42) [20]

В реальной жизни скорость сравнения двух файлов не так существенна, как кажется. Я делаю тупо, считаю CRC и сравниваю его и размер. Если совпало, то в 99% файлы идентичны.


 
DVM ©   (2012-11-16 15:59) [24]


> Игорь Шевченко ©   (16.11.12 15:50) [23]


> считаю CRC и сравниваю его и размер.

А зачем считать CRC если можно просто побайтно сравнить? CRC же тоже потребует прохода по всем байтам и ее вычислени заведомо медленнее, если речь именно о CRC, а не о Checksum. Имеет смысл, если только один файл многократно надо сравнивать с другими.


 
Игорь Шевченко ©   (2012-11-16 16:03) [25]

DVM ©   (16.11.12 15:59) [24]


> А зачем считать CRC


Я большие группы файлов обрабатываю с целью поиска идентичных. Большие - десятки и сотни тысяч файлов.


 
DVM ©   (2012-11-16 16:06) [26]


> Игорь Шевченко ©   (16.11.12 16:03) [25]


> Я большие группы файлов обрабатываю с целью поиска идентичных

ясно

Кстати я еще погонял тест на разных файлах, очень сильно влияет на результаты кэширование, т.е. фактически делать два раза тест на одних и тех же файлах уже бессмысленно. В среднем быстрее отображенные файлы, да.


 
RWolf ©   (2012-11-16 16:15) [27]


> Я большие группы файлов обрабатываю с целью поиска идентичных.
>  Большие - десятки и сотни тысяч файлов.

опасно при такой обработке полагаться на 32-битный CRC.
есть приличный (1/65536) шанс ложного совпадения.
лучше какую-нибудь хэш-функцию из распространённых.


 
Leonid Troyanovsky ©   (2012-11-16 16:28) [28]


> Unknown1   (16.11.12 11:16)  

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

http://www.delphimaster.net/view/2-1187943014

--
Regards, LVT.


 
Игорь Шевченко ©   (2012-11-16 16:42) [29]

RWolf ©   (16.11.12 16:15) [27]


> опасно при такой обработке полагаться на 32-битный CRC.


Как выяснилось - не опасно. К тому же я считаю 16-битный CRC


> есть приличный (1/65536) шанс ложного совпадения.


Это при 16-битном, не так ли ?


 
RWolf ©   (2012-11-16 16:44) [30]


> Это при 16-битном, не так ли ?


при 16-битном всё ещё хуже: 1/256.

http://ru.wikipedia.org/wiki/Парадокс_дней_рождения


 
Игорь Шевченко ©   (2012-11-16 16:49) [31]

RWolf ©   (16.11.12 16:44) [30]

Ты невнимательно читаешь.


> считаю CRC и сравниваю его и размер. Если совпало, то в
> 99% файлы идентичны.


 
RWolf ©   (2012-11-16 16:52) [32]


> [31]

да я понял, что размер; просто попадаются наборы файлов одинакового размера — растровые изображения, иконки, карты и т.п., и вот на таких наборах можно поймать коллизию.


 
Игорь Шевченко ©   (2012-11-16 16:55) [33]

RWolf ©   (16.11.12 16:52) [32]

в 99% коллизий не наблюдается. В том числе и среди растровых изображений.


 
QAZ9   (2012-11-16 17:31) [34]


> DVM ©   (16.11.12 16:06) [26]

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


 
QAZ9   (2012-11-16 17:37) [35]

заодно дефрегментацию этих файлов сделай


 
DVM ©   (2012-11-16 18:17) [36]


> QAZ9   (16.11.12 17:31) [34]
>
> > DVM ©   (16.11.12 16:06) [26]
>
> нет, быстрей буфер если убрать всякие обертки аля "поток"

обертки практически не ухудшают результат, если не по одному байту читать


 
QAZ9   (2012-11-16 20:16) [37]


> обертки практически

ну как сказать :) иногда катастрофически ухудшают
лично я тестил с результатом в пользу буфера + у него есть некоторые плюсы которые с первого взгляда не бросаются в глаза
а вот функции меморимапеда даже некоректно переведены в самой дельфе (7й версии например)


 
Inovet ©   (2012-11-16 20:45) [38]

> [37] QAZ9   (16.11.12 20:16)
> а вот функции меморимапеда даже некоректно переведены в
> самой дельфе (7й версии например)

Куда переведены заголовки что ли? И что, по этой причине запрещается пользоваться отображением файлов на память?


 
bems ©   (2012-11-16 21:08) [39]


> почему?
>
> Если файл большой, система скажет, что готово, отображено
> все. А потом, за кулисами, будет лазить в файл.
>
> против
>
> Зачитать в память все. Если не сбросит в своп - все в память.
>
в такой постановке они равны, а чтение в буффер не лучше


> Но тут надо учитывать, что сравнивать все равно придет поблочно
> читая из отображенных в память файлов, т.к. натравливать
> на них CompareMem не очень практично, т.к. при больших файлах
> этот процесс нельзя будет прервать и в реальной жизни так
> не удобно.

весь замапленный файл уже считай буффером и читать оттуда поблочно не придётся. А если нужно прервать то можно или или написать свою функцию сравнения, или вызывать CompareMem поблочно, но при этом блоки не копировать лишний раз


 
DVM ©   (2012-11-17 00:17) [40]


> bems ©   (16.11.12 21:08) [39]


>  или вызывать CompareMem поблочно, но при этом блоки не
> копировать лишний раз

Вот если так делать, то отличия с поблочным чтением прямо из файлов с диска становятся не очень заметны. Наибольший выигрыш удалось получить, если CompareMem натравливать на целиком буфера. Но этот способ имеет недостатки.

Вообще со всем этим отображением на 32 бит системах проблем может быть больше чем кажется. Если память процесса представляет собой решето из занятых и свободных блоков, а это очень может получиться так, если в процессе работы он часто что-то будет отображать в память и параллельно выделять память для своих нужд, то спроецировать туда что-то значительное не выйдет.


 
bems ©   (2012-11-17 13:15) [41]


> от если так делать, то отличия с поблочным чтением прямо
> из файлов с диска становятся не очень заметны. Наибольший
> выигрыш удалось получить, если CompareMem натравливать на
> целиком буфера. Но этот способ имеет недостатки.

может блоки слишком маленькие брались?


> Вообще со всем этим отображением на 32 бит системах проблем
> может быть больше чем кажется. Если память процесса представляет
> собой решето из занятых и свободных блоков, а это очень
> может получиться так, если в процессе работы он часто что-
> то будет отображать в память и параллельно выделять память
> для своих нужд, то спроецировать туда что-то значительное
> не выйдет

да, на х32 могут быть проблемы с размером, но х64 будет жить дольше


 
QAZ9   (2012-11-17 17:11) [42]


> Если память процесса представляет собой решето

а в х64 типа решета не будет? :)


 
DVM ©   (2012-11-17 17:20) [43]


> QAZ9   (17.11.12 17:11) [42]

будет, но с более большими дырками, огромными.


 
QAZ9   (2012-11-17 17:26) [44]


> DVM ©   (17.11.12 17:20) [43]

эммм...
ну было 2 гига памяти - стало 4, где огромность ?
как был через Ж написан софт в х32, так его и перекомпилили на х64
и?
на данный момент времени программисты деградируют быстрей чем развиваются производители железа, зато работают удобно и на расслабоне


 
bems ©   (2012-11-17 17:35) [45]

стало не 4 гига а 256 байт в восьмой степени


 
bems ©   (2012-11-17 17:36) [46]

вообще да, они деградируют


 
QAZ9   (2012-11-17 17:48) [47]


> bems ©   (17.11.12 17:35) [45]

я не про диапазон адресов из википедии, а про стандартные бытовые компы которые продаются в магазине, было 2ядра\2гига , стало 4ядра\4гига


 
DVM ©   (2012-11-17 17:49) [48]


> QAZ9   (17.11.12 17:26) [44]
>
> > DVM ©   (17.11.12 17:20) [43]
>
> эммм...
> ну было 2 гига памяти - стало 4, где огромность ?

во-первых, адресное пространство 32 бит программы - 4 гб, а не 2.
во-вторых, адресное пространство 64 бит программы - 48 бит в реале для AMD64 расширения (которое в интел тоже используется), а это 4 петабайта 256 терабайт.


 
DVM ©   (2012-11-17 17:51) [49]


> QAZ9   (17.11.12 17:48) [47]
>
> > bems ©   (17.11.12 17:35) [45]
>
> я не про диапазон адресов из википедии, а про стандартные
> бытовые компы которые продаются в магазине, было 2ядра\2гига
> , стало 4ядра\4гига

причем тут это вообще.

Виртуальное адресное пространство никаким боком не связано с размером оперативной памяти.


 
DVM ©   (2012-11-17 17:58) [50]


> DVM ©   (17.11.12 17:49) [48]


> 4 петабайта 256 терабайт.

правда в Windows есть еще свое ограничение, а именно вот http://msdn.microsoft.com/en-us/library/aa366778(VS.85).aspx но все равно это 8 терабайт


 
QAZ9   (2012-11-17 18:07) [51]


> DVM ©   (17.11.12 17:51) [49]

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


 
DVM ©   (2012-11-17 18:13) [52]


> QAZ9   (17.11.12 18:07) [51]


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

Интересует того, кто проецирует в память файлы на диске, мы о них речь ведем не уходи от темы. При наличии 64 бит пространства есть больше адресов, куда можно спроецировать больший кусок с диска и меньше вероятность что там не окажется свободного блока нужного размера. В 32 бит пространстве таких шансов на  три-четыре порядка меньше и всего делов.


 
QAZ9   (2012-11-17 18:24) [53]


> того, кто проецирует

т.е. ленивого программиста которому надо проще а не лучше?

> есть больше адресов, куда можно спроецировать

так оно ж виртуальное , и со стороны програмиста линейное, несмотря на то что физически это может быть >100500 фрагментов

и кроме того нам в душе не известно как это выглядит внутри винды, ибо занятая системными буферами память не учитывается не в каких счетчиках
а когда работа с файлом идет со случайным доступом, то может быть занята совершенно вся оперативка


 
DVM ©   (2012-11-17 18:39) [54]


> QAZ9   (17.11.12 18:24) [53]


> > того, кто проецирует
>
> т.е. ленивого программиста которому надо проще а не лучше?
>

Использование MMF вовсе не проще и не лучше, чем их неиспользование. Что лучше, что хуже, надо решать в конкретном случае.  Сами по себе MMF отличное средство во многих случаях.


> так оно ж виртуальное , и со стороны програмиста линейное,
>  несмотря на то что физически это может быть >100500 фрагментов

И что? Фрагментируется именно виртуальное пространство, про физическое вообще речи не идет, т.к. мы с ним напрямую не работаем. В 32 бит системах фрагментация будет более выражена.

Я не понимаю, что ты ко мне пристал, что ты мне хочешь доказать?

Тот факт, что в 32 бит программах меньше шансов спроецировать даже 2 гб файл, чем в 64 бит сомнений не вызывает. Что еще?


 
QAZ9   (2012-11-17 18:48) [55]

ну как?
тут же на форуме принято как минимум на 6 страниц разводить дискуссии до которых ТС уже давно наплевать :)
ты же МАСТЕР - должен знать уже ...


 
bems ©   (2012-11-17 18:58) [56]


> я не про диапазон адресов из википедии, а про стандартные
> бытовые компы которые продаются в магазине

ограничение по реальной оперативе одинаково действует и на MMF и на ручное чтение. Проблемы с размером MMF вытекают только из количества доступных адресов.

Мне удалось забить $63B22D5F377 байт виртуального АП, да это далеко не 64 бита. Но и далеко не 32


 
bems ©   (2012-11-17 19:06) [57]


> Проблемы с размером MMF вытекают только из количества доступных
> адресов.

непрерывных свободных адресов, конечно же


 
QAZ9   (2012-11-17 19:32) [58]


> Мне удалось забить $63B22D5F377

что значит забить? и заметь, ключевое слово "виртуальное"


 
bems ©   (2012-11-17 22:49) [59]


> что значит забить?

замаппить туда файл. Не всю память забивал единым куском, но при этом тесте я ставил цель проверить инфу DVM про 48 бит. Кажется он прав.


>  и заметь, ключевое слово "виртуальное"

тебе выше уже несколько раз объяснили что именно виртуальная память и является источником ограничения на размер MMF, а вовсе не физическая. Ясен пень что столько оперативы у меня нет.
Но выше приводился аргумент что дескать MMF хуже, потому что не могут быть большими. Ну вот я показал что могут.


 
DVM ©   (2012-11-17 23:08) [60]


> Но выше приводился аргумент что дескать MMF хуже, потому
> что не могут быть большими. Ну вот я показал что могут.

Эээ. Если это про [40], то я же там про 32 бит говорил, в 64 бит пожалуйста, и терабайт замаппируется.


 
bems ©   (2012-11-18 00:40) [61]

в [41] и я говорил что на х64 уже норм.
не, там выше товарисч утверждал сначала что и на х64 все плохо, потому что тоже самое решето (только на 4 гектара почему-то), потом говорил что там какое-то значение имеет физическая оператива и по сумме всего этого получалось что и на х64 они хуже чтения вручную.
Вот я собственно и доказываю что по скорости не хуже, а по размеру на х64 не хуже.


 
QAZ9   (2012-11-18 17:10) [62]


> только на 4 гектара почему-то

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

> Вот я собственно и доказываю что по скорости не хуже

ну раз пошла такая пьянка давай код сравнения скорости ,проверим


 
bems ©   (2012-11-19 03:54) [63]


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

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


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


> 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);?


 
DVM ©   (2012-11-19 11:07) [65]


> Unknown1   (19.11.12 10:35) [64]


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

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

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


 
QAZ9   (2012-11-19 11:18) [66]


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

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

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


 
DVM ©   (2012-11-19 11:22) [67]


> QAZ9   (19.11.12 11:18) [66]


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

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


 
DVM ©   (2012-11-19 11:24) [68]

Код для сравнения с помощью буфера выше. Соответственно нужен код, для маппинга файлов. Я использовал опять же свою обертку для 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:29) [69]

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

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


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

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


 
bems ©   (2012-11-19 15:04) [71]


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


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

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


а если по 2 гб ?


 
DVM ©   (2012-11-27 11:43) [73]


> 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;


 
QAZ9   (2012-11-27 11:48) [74]

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


 
DevilDevil ©   (2012-11-27 14:11) [75]

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

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


 
brother ©   (2012-11-27 14:32) [76]

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

с чего бы?


 
DVM ©   (2012-11-27 16:35) [77]


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


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

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


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

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


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

> 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
);


 
anatoly podgoretsky ©   (2012-11-27 17:45) [79]

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

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


 
DVM ©   (2012-11-27 17:53) [80]


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


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

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

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


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

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


 
Anatoly Podgoretsky ©   (2012-11-27 20:29) [82]

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

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



Страницы: 1 2 3 вся ветка

Форум: "Начинающим";
Текущий архив: 2013.07.21;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.7 MB
Время: 0.005 c
2-1353050219
Unknown1
2012-11-16 11:16
2013.07.21
сравнение 2-х TFileStream


15-1362294840
TUser
2013-03-03 11:14
2013.07.21
100% тест на русскость ))


15-1362228850
xayam
2013-03-02 16:54
2013.07.21
Поделитесь опытом


11-1246891762
Galkov
2009-07-06 18:49
2013.07.21
Про дружбу KOL и FPC


3-1291201543
StriderMan
2010-12-01 14:05
2013.07.21
isc_shutinprog





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский