Форум: "Потрепаться";
Текущий архив: 2004.09.05;
Скачать: [xml.tar.bz2];
Внизкритика кода DMClient Найти похожие ветки
← →
nikkie © (2004-08-12 14:28) [40]тьфу, не 0x12, а 0x13, конечно.
по-моему строку
if p[1] = #10 then Inc(p);
выкинуть надо, а 0x13 заменить на 0x10.
← →
nikkie © (2004-08-12 14:34) [41]>[39] Anatoly Podgoretsky © (12.08.04 14:26)
>Упрости Readln(F);
>и поменяй местами
Fay:1500 ticks spent
Std:13312 ticks spent
пробовал несколько раз, результат воспроизводим.
проверял также на 2х идентичных копиях файла, чтобы исключить вопросы перекоса из-за кеширования. проверял на FAT и NTFS, результат примерно тот же.
← →
Anatoly Podgoretsky © (2004-08-12 14:39) [42]Вот теперь после этого можно говорить о некоторой достверности теста, всегда надо учитывать кеширование.
← →
Danilka © (2004-08-12 14:42) [43]Хм, у меня такие результаты:
Fay:1734 ticks spent
Std:9016 ticks spent
когда примерно такие:
Fay:9078 ticks spent
Std:1797 ticks spent
← →
Danilka © (2004-08-12 14:43) [44]второй вариант, это когда сначала Std, затем Fay
← →
nikkie © (2004-08-12 14:47) [45]>Danilka
размер файла какой?
← →
Danilka © (2004-08-12 14:49) [46]3633087
:))
← →
Anatoly Podgoretsky © (2004-08-12 14:50) [47]Danilka © (12.08.04 14:43) [44]
У меня были такие же результаты в более давних испытаниях, вечером дома тест проведу на этих процедурах.
nikkie © (12.08.04 14:47) [45]
А вот размер файла ни причем, не надо привязываться к этому, будем лучше говорить о размерах от 0 до 2 гб, так честнее будет.
← →
nikkie © (2004-08-12 14:52) [48]3633087
:))
надо же, какой у меня диск тормознутый...
← →
Anatoly Podgoretsky © (2004-08-12 14:56) [49]nikkie © (12.08.04 14:52) [48]
Вечером возможно вообще будешь плакать :-)
← →
cyborg © (2004-08-12 14:58) [50]Вот переписал, получается весьма быстро:
Program test2;
Uses SysUtils,Windows;
function GetCPUTick: int64; assembler;
asm
db 0fh,31h;
end;
Function GetNumStrings(Const P : Pointer; Size : Longint) : Longint;
Var
Num : Longint;
i : Longint;
begin
Num:=0;
for i:=0 to Size-1 do
begin
if Byte(Pointer( Longint(P)+i )^)=10 then inc(Num);
end;
GetNumStrings:=Num;
end;
Const
BlockSize = 4096;
Var
Time : Int64;
Time2 : Int64;
F : File;
P : Pointer;
Size : Longint;
NumStrings : Longint;
iRead : Longint;
ReadSize : Longint;
BEGIN
Time:=0;
NumStrings:=0;
if ParamCount>0 then
if FileExists(ParamStr(1)) then
begin
Time2:=GetTickCount;
Time:=GetCPUTick;
AssignFile(F,ParamStr(1));
Reset(F,1);
Size:=FileSize(F);
GetMem(P,BlockSize);
for iRead:=0 to (Size div BlockSize) do
begin
ReadSize:=Size - (BlockSize*iRead);
if ReadSize>BlockSize then ReadSize:=BlockSize;
BlockRead(F,P^,ReadSize);
Inc(NumStrings,GetNumStrings(P, ReadSize));
end;
FreeMem(P,BlockSize);
CloseFile(F);
Time:=GetCPUTick-Time;
Time2:=GetTickCount-Time2;
end;
WriteLn("File: ",ParamStr(1));
WriteLn("FileSize: ",Size);
WriteLn("Number of strings - ",NumStrings);
WriteLn("Speed CPU ticks - ",Time);
WriteLn("Speed time - ",Time2);
WriteLn;
WriteLn("Press ENTER:");
ReadLn;
END.
Вроде не глючит. :)
Константа BlockSize указывает размер блока по сколько байт читать.
Результат такой:
File: G:\DOCUMENTS\DOC\80486.TXT
FileSize: 2076287
Number of strings - 40719
Speed CPU ticks - 40108688
Speed time - 50
Press ENTER:
nikkie пользуйся моей функцией ;)
← →
Anatoly Podgoretsky © (2004-08-12 15:01) [51]Я уже подчеркивал, что такой поиск строк не корректен, надо проверять на #13#10
ReadLn это делает честно.
← →
Anatoly Podgoretsky © (2004-08-12 15:03) [52]Да у меня нет тестовой базы, поэтому буду проверять на сгенерированой, со строками размером от 10 до 100 символов, как типичное для текстовых файлов. Размером где ни будь в 4-6 мегабайт.
← →
cyborg © (2004-08-12 15:05) [53]
> [51] Anatoly Podgoretsky © (12.08.04 15:01)
не согласен я :), в юниксовом формате текста переход строки только #10.
Поэтому корректно только его проверять! Попадётся такой текст, у вас покажет что там всего одна строка.
← →
Anatoly Podgoretsky © (2004-08-12 15:11) [54]cyborg © (12.08.04 15:05) [53]
Про Юникс и Мак давай пока не будем, поскольку речь идет о клиенте под платформу Win32
Нам обязан повтоемый резултат вне зависимости кто писал функцию, можно конечно сделать скидку, мол гарантируем, что исходные данные будут обязательно правильные для нашей функцией, но это не чисто. Это как с обсуждаемыми калькуляторами.
← →
Anatoly Podgoretsky © (2004-08-12 15:13) [55]Как насчет исходных данных, нет возражений, что я их сгенерирую искуственно или кто ни будь пускай мне бросит их на почту или ссылку на веб сайт, откуда я иогу их взять для тестирования.
← →
Vss (2004-08-12 15:22) [56]Подскажите начинающему, как ON Line понаблюдать за Вашей беседой?
← →
cyborg © (2004-08-12 15:27) [57]Есть ошибка, исправить надо:
GetMem(P,BlockSize);
if Size>0 then NumStrings:=1;
for iRead:=0 to (Size div BlockSize) do
← →
cyborg © (2004-08-12 15:31) [58]
> [54] Anatoly Podgoretsky © (12.08.04 15:11)
Почему же не будем, не обязательно же сидеть под юниксом, чтобы читать текстовые файлы. Я например скачаю у себя с сервера скрипт для правки, он уже с таким переходом строки идёт, и что же, теперь, если я в виндвс, то мне нельзя ничего с ним делать, и я так не играю? Обычными редакторами крайне трудно такие файлы редактировать, так как они (строки) идут в них одной строкой, в TotalCommander-е только нормально могу просмотреть смодержимое такого файла.
Давайте уж лучше будем!
← →
KSergey © (2004-08-12 15:34) [59]> [56] Vss (12.08.04 15:22)
F5
← →
Anatoly Podgoretsky © (2004-08-12 20:00) [60]Ну вот проверил все три метода, данные такие
файл размером 5б5 мб, ровно 100000 строк
самопальные утилиты с задачей не справились, насчитали только 99999 строк. Временные результаты, измерение проводилось с помощью системных и процессорных тактов. Каждое измерение проводилось минимум три раза, что бы уменьшить погрешности от кеширования.
ReadLn 387 261 396 тактов, 156 мс
Mapping (Fay) 33 353 196 тактов, 15 мс
BlockRead (cyborg) 46 791 724 тактов, 32 мс
Измерение в мс естественно не точные, не отражающие сути
← →
Anatoly Podgoretsky © (2004-08-12 20:06) [61]Дополнение к третьему измерению, показание в тиках сильно прыгают, но в основном около 32 мс
Расзер файла не 5б5 :-) а 5,5 мб
← →
Fay © (2004-08-12 20:12) [62]2 nikkie © (12.08.04 13:56) [27]
Только в 2 раза. Больше года так не ошибался - очень подозрительно смотрелся исходный вариант. 8)
← →
cyborg © (2004-08-12 21:39) [63]При буффере 4 кило медленно читает :)
Вот размер буффера подбирал:
File: I:\VIDEO\Куда уж хуже.AVI
FileSize: 717850624
Number of strings - 3695343
Buffer=4 kb
Speed CPU ticks - 15760752043
Speed time - 19128
Buffer=8 kb
Speed CPU ticks - 15541846027
Speed time - 18867
Buffer=16 kb
Speed CPU ticks - 15537888368
Speed time - 18857
Buffer=32 kb
Speed CPU ticks - 15542828862
Speed time - 18867
Buffer=64 kb
Speed CPU ticks - 15569491958
Speed time - 18897
Buffer=96 kb
Speed CPU ticks - 17620727761
Speed time - 21391
Buffer=128 kb
Speed CPU ticks - 22125965570
Speed time - 26858
Buffer=1024 kb
Speed CPU ticks - 34017783595
Speed time - 41289
Для рассчётов размер буффера поставил 32 кило.
Файл тектсовый ~2 мегабайта скопипастил 20 раз, получилось 41 525 740 байт, сначала (в тестовой программе) прогонял все три теста не учитывая время, затем опять три теста засекая время, результаты такие:
Cbrg - 814381
Number of strings - 814381
Speed CPU ticks - 432005600
Speed time - 521
Std - 814381
Number of strings - 814381
Speed CPU ticks - 1141449599
Speed time - 1382
Fay - 814381
Number of strings - 814381
Speed CPU ticks - 537899487
Speed time - 661
Прогнал по тесту лог-файл моего сервера (cyborghome.ru.txt - 1 155 495 байт):
Cbrg - 4142
Number of strings - 4142
Speed CPU ticks - 17302976
Speed time - 20
Std - 4141
Number of strings - 4141
Speed CPU ticks - 29207198
Speed time - 40
Fay - 0
Number of strings - 0
Speed CPU ticks - 16504663
Speed time - 20
Переход строки там #10, Тест FAY провалился, ReadLn во Фрипаскале такой переход строки понимает.
← →
Fay © (2004-08-12 21:43) [64]2 cyborg © (12.08.04 21:39) [63]
Правила на ходу меняем? Очень странно. Можно подумать, что мой пример нельзя доработать. Какая глупость.
← →
cyborg © (2004-08-12 21:43) [65]Вот код программы:
Program test2;
Uses SysUtils,Windows;
function GetCPUTick: int64; assembler;
asm
db 0fh,31h;
end;
//===========================================================================//
function GetLineCountCbrg(const FileName : string) : Integer;
Const
BlockSize = 1024*32; //размер читаемого блока
Var
F : File;
P : Pointer;
Size : Longint;
NumStrings : Longint;
iRead : Longint;
ReadSize : Longint;
//+++
Function GetNumStrings(Const P : Pointer; Size : Longint) : Longint;
Var
Num : Longint;
i : Longint;
begin
Num:=0;
for i:=0 to Size-1 do
begin
if Byte(Pointer( Longint(P)+i )^)=10 then inc(Num);
end;
GetNumStrings:=Num;
end;
//+++
begin
Result:=0;
NumStrings:=0;
if not FileExists(FileName) then Exit;
AssignFile(F,FileName);
Reset(F,1);
Size:=FileSize(F);
GetMem(P,BlockSize);
if Size>0 then NumStrings:=1;
for iRead:=0 to (Size div BlockSize) do
begin
ReadSize:=Size - (BlockSize*iRead);
if ReadSize>BlockSize then ReadSize:=BlockSize;
BlockRead(F,P^,ReadSize);
Inc(NumStrings,GetNumStrings(P, ReadSize));
end;
FreeMem(P,BlockSize);
CloseFile(F);
Result:=NumStrings;
end;
//===========================================================================//
function GetLineCountStd(const FileName : string) : Integer;
var
F: TextFile;
s: String;
begin
Result := 0;
if not FileExists(FileName) then begin
Exit;
end;
AssignFile(F, FileName);
Reset(F);
try
while not EOF(F) do begin
Readln(F, s);
Inc(Result);
end;
finally
CloseFile(F);
end;
end;
//===========================================================================//
function GetLineCountFay(const cFileName : string) : Integer;
var
h, m, sz : DWORD;
v, p, pe : PChar;
begin
Result := 0;
h := CreateFile(PChar(cFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if h = INVALID_HANDLE_VALUE then Exit;
m := 0;
v := nil;
try
sz := GetFileSize(h, nil);
// if (sz = INVALID_FILE_SIZE) or (sz = 0) then Exit;
m := CreateFileMapping(h, nil, PAGE_READONLY, 0, 0, nil);
if m = 0 then Exit;
v := MapViewOfFile(m, FILE_MAP_READ, 0, 0, 0);
if v = nil then Exit;
p := v - 1;
pe := p + sz;
if pe^ <> #10 then Result := 1;
repeat
Inc(p);
if p^ = #13 then
begin
Inc(Result);
if p[1] = #10 then Inc(p);
end;
until p >= pe;
finally
if v <> nil then UnmapViewOfFile(v);
if m <> 0 then CloseHandle(m);
CloseHandle(h);
end;
end;
//===========================================================================//
VAR
Time : Int64;
Time2 : Int64;
StringCount : Longint;
BEGIN
Time:=0;
Time2:=0;
WriteLn("File: ",ParamStr(1));
if ParamCount>0 then
if FileExists(ParamStr(1)) then
begin
GetLineCountCbrg(ParamStr(1));
GetLineCountStd(ParamStr(1));
GetLineCountFay(ParamStr(1));
Time2:=GetTickCount;
Time:=GetCPUTick;
StringCount:=GetLineCountCbrg(ParamStr(1));
Time:=GetCPUTick-Time;
Time2:=GetTickCount-Time2;
WriteLn("Cbrg - ",StringCount);
WriteLn("Number of strings - ",StringCount);
WriteLn("Speed CPU ticks - ",Time);
WriteLn("Speed time - ",Time2);
WriteLn;
Time2:=GetTickCount;
Time:=GetCPUTick;
StringCount:=GetLineCountStd(ParamStr(1));
Time:=GetCPUTick-Time;
Time2:=GetTickCount-Time2;
WriteLn("Std - ",StringCount);
WriteLn("Number of strings - ",StringCount);
WriteLn("Speed CPU ticks - ",Time);
WriteLn("Speed time - ",Time2);
WriteLn;
Time2:=GetTickCount;
Time:=GetCPUTick;
StringCount:=GetLineCountFay(ParamStr(1));
Time:=GetCPUTick-Time;
Time2:=GetTickCount-Time2;
WriteLn("Fay - ",StringCount);
WriteLn("Number of strings - ",StringCount);
WriteLn("Speed CPU ticks - ",Time);
WriteLn("Speed time - ",Time2);
end;
WriteLn;
WriteLn("Press ENTER:");
ReadLn;
END.
// if (sz = INVALID_FILE_SIZE) or (sz = 0) then Exit; закомментировал так, как фрипаскаль не знает константы INVALID_FILE_SIZE (или я не нашол модуль требуемый), но этот участок не важен для данного теста.
← →
cyborg © (2004-08-12 21:46) [66]
> [64] Fay © (12.08.04 21:43)
Какие правила я меняю? Про доработку ествественно можно, я сказал провалился не имея ввиду "ха ха ха, ха ха, слабак!", а имея ввиду спор с Анатолием ;).
← →
Danilka © (2004-08-12 21:50) [67]Вот, дома померил, 7 измерений, файл 7.6МБ, средние результаты:
Std:14672 ticks spent
Fay:3781 ticks spent
Fay:3890 ticks spent
Std:14906 ticks spent
Странно, почему все-таки так сильно отличаются от: [41] и [61]..
Anatoly Podgoretsky ©, nikkie © а у вас какие операционки? У меня и дома и на работе ВинХР. Просто, не пойму, от чего могут быть расхождения более чем в два раза.
← →
Anatoly Podgoretsky © (2004-08-12 21:56) [68]Fay © (12.08.04 21:43) [64]
Не стоит обращать на это внимание, мы именно рассматривает платформу Win32 другие платформы не заказывалист. А вот то что количество строк читается не верно это очень плохо. Я не анализировал код для поиска ошибки. В принчипе для примера это не важно, нас интересовала производительность по подсчету количества строк.
cyborg © (12.08.04 21:46) [66]
Сообственно я особо и не спорил, тем более что подсчет только малая часть задач и в ней можно достигнуть повышеного быстродействия. Ну в принципе данных тестов нам достаточнои не столько их ха результатов, сколько из за демонстрации трех кардинально различных методов работы.
← →
Anatoly Podgoretsky © (2004-08-12 22:05) [69]Danilka © (12.08.04 21:50) [67]
открою большой секрет, дело в не в операционках (я проверял на XP PRO, NTFS) а в объеме оперативной памяти, у меня 1,5 гб, даже кинофильмы второй раз считываеются из диского кеша :-)
Плюc PIV 2.4C c гипер тредингом и двухканальной памятью, я паралельно запуска показ их ТИ тюнера, время меняется незначительно.
На 512 мб я наблюдал именно такую картину, смена порядка тестов, показывало разные результаты для них. Для проверки надо делать несколько измерений подряд, например запуска отдельный тест в обработчике отдельной клавиши, для тестов у меня было сделано три кнопки и сразу проводилось три попытки, все три результата выводились в отдельные метки, при желании можно запускать любой тест несколько раз подряд и в любом порядке.
То есть у меня получается чистое измерение без влияния параметров винчестера. Хотел похвалиться скорость винчестера, а из за этого не получилось. :-)
← →
Anatoly Podgoretsky © (2004-08-12 22:07) [70]Цикл генерации тестового набора выглядел так
For I := 1 nj 100000 do WriteLn(F, случайная строка от 10 до 100 символов). Очень удобно увидеть ошибки тестов :-)
← →
Fay © (2004-08-12 22:31) [71]1) Днём было ~20. Сейчас меньше. Хрень какая-то.
2) Порядок имеет значение.
3) Длина строк имеет значение.
Сейчас (вечером 8)) минимальный выигрыш ~4 раза. Максимальный, действительно 20, но только на строках длины < 10.
← →
Danilka © (2004-08-13 08:56) [72][69] Anatoly Podgoretsky © (12.08.04 22:05)
Да я про другое. Про то, что в [41] и [61] разница на глаз в 8-10 раз по-скорости между Fay и Std, а у меня в 4-5 раз.
[71] Fay © (12.08.04 22:31)
Порядок имеет значение, но при большом количестве проведенных тестов он влияет уже не так сильно.
На счет длинны строк. В [41] и [43] тестировалось на практически одинаковых файлах, список тем от "Потрепаться", только у nikkie он больше, что вполне естественно, т.к. он своим клиентом раньше меня начал пользоваться, но мое содержимое один в один есть у него + то, что он раньше насобирал.
То-есть, странно то, что на одинаковых файлах одинаковый тест на разных машинах дает отношение скоростей в 2 раза.
Возможно, это тоже, как-то связано с объемом памяти? У меня и дома и на работе 256МБ. У Анатолия 1.5ГБ (блин, я тоже так хочу).
← →
Danilka © (2004-08-13 09:03) [73]Или, может скорость памяти влияет? У меня старая и медленная, у Анатолия двухканальная.
← →
Anatoly Podgoretsky © (2004-08-13 09:28) [74]Danilka © (13.08.04 09:03) [73]
Двухканальная DDR400, FSB 800, поэтому эта скорость обеспечивается и кеш загружается не за два такта а за один, ширина кэша у P4c - 128 бит, ширина памяти 64 бита
Снижение на разных машинах можно объяснить разными процессорами и разным объемом памяти. На P4e например будет другое количество тактов процессора и другое соотношение между тестами.
← →
nikkie © (2004-08-13 14:18) [75]>[54] Anatoly Podgoretsky
>Про Юникс и Мак давай пока не будем, поскольку речь идет о клиенте под платформу Win32
cyborg прав - и на Windows могут быть файл с переводом строки 0A вместо 0D 0A. достаточно может оказаться просто файл через ftp пронести. в конце концов мы добиваемся совпадения с тем, как работает Readln - я проверил, он считает оба варианта за перевод строки, 0D за перевод не считается. поэтому для подсчета числа строк достаточно считать количество 0A.
← →
nikkie © (2004-08-13 14:20) [76]>[62] Fay
>Только в 2 раза. Больше года так не ошибался - очень подозрительно смотрелся исходный вариант. 8)
ну а у меня 100% попадание :)
[17]
>думаю, что пользователь не заметит разницы.
[37]
>0.01 секунды вместо 0.1 секунды.
за код спасибо, надо только исправитьp := v - 1;
pe := p + sz;
if pe^ <> #10 then Result := 1;
repeat
Inc(p);
if p^ = #13 then
begin
Inc(Result);
if p[1] = #10 then Inc(p);
end;
until p >= pe;
наp := v;
pe := p + sz - 1;
if pe^ <> #10 then Result := 1;
while p <= pe do begin
if p^ = #10 then
Inc(Result);
Inc(p);
end;
получается проще и корректнее. а если заменить ещеif pe^ <> #10 then Result := 1;
наResult := 1;
получится еще корректнее, по крайней мере, FAR так считает строки, хоть это и несовпадает с Readln-версией.
← →
nikkie © (2004-08-13 14:20) [77]про FileMapping у меня мысль была, не было времени и необходимости ей заниматься. если бы возникли серьезные тормоза, то задумался бы. но скорее стал бы хранить количество строк в первой строке файла или в рядом лежащем.
кстати, по поводу FileMapping. твоя функция заведомо не будет работать на файлах размера 2Gb и немногим меньше (Readln надеюсь будет работать, хотя не проверял...). получается, что CreateFileMapping надо делать по кусочкам, не знаю только какого размера...
а еще озадачивает комментарийWindows 95: MapViewOfFile may require the swapfile to grow. If the swapfile cannot grow, the function fails.
Windows NT/2000: If the file-mapping object is backed by the paging file (hFile is INVALID_HANDLE_VALUE), the paging file must be large enough to hold the entire mapping. If it is not, MapViewOfFile fails.
Note To guard against an access violation, use structured exception handling to protect any code that writes to or reads from a memory mapped view. For more information, see Reading and Writing.
а в разделе Reading and Writing:Note Reading from or writing to a file view can cause an exception. For example, accessing a mapped file that resides on a remote server can generate an exception if the connection to the server is lost. Exceptions can also occur because of a full disk, because the file is shared and a different process has locked a byte range, or because of an underlying device failure or memory allocation failure. To guard against exceptions due to input and output (I/O) errors, all attempts to access memory mapped files should be wrapped in structured exception handlers.
If you are mapping a compressed or sparse file on an NTFS partition, there is additional potential for an I/O error when paging in a portion of the file. In this case, the address space mapped by MapViewOfFile may not be backed by allocated disk space. This is because a sparse file can have regions of zeroes for which NTFS does not allocate disk space, and a compressed file can take up less disk space than the actual data that it represents. If you read from or write to a portion of a sparse or compressed file that is not backed by disk space, the operating system may try to allocate disk space. If the disk is full, this can result in an exception indicating an I/O error. For more information, see File Compression, Sparse Files, and Structured Exception Handling.
так что думается мне, что BlockRead aka ReadFile надежнее будет.
← →
Fay © (2004-08-13 22:32) [78]С большими файлами работать не так приятно, но можно. Коран не запрещает использовать MapViewOfFile/UnmapViewOfFile несколько раз.
Но на таких файлах и разница в скорости будет заметнее.
← →
Fay © (2004-08-13 22:38) [79]По поводу "озадачивающих" комментиариев - всё не так ужасно 8)
← →
nikkie © (2004-08-13 23:04) [80]>Коран не запрещает использовать MapViewOfFile/UnmapViewOfFile несколько раз.
значит надо использовать... пока что получается, ты привел нерабочий код. так ведь? ну хорошо, работающий, но при некоторых ограничениях... :)
кстати, какими кусками MapView будешь делать? 32K? будет после выигрыш по сравнению с BlockRead?
>По поводу "озадачивающих" комментиариев - всё не так ужасно 8)
честно - я не знаю, в деталях, что такое SEH. означает ли это, что мы рискуем получить AV при работе со сжатым NTFS-томом, файлом на share или любым файлом на Win98?
ты продолжаешь настаивать, что MapViewOfFile - это наиболее правильный способ?
ЗЫ ты, кстати, обещал в 100 раз ускорить GetLastQuestionTimeStamp. опиши хотя бы, что ты собираешь оптимизировать там - работу с файлом или заменить TStringList на парсинг строки? у меня такое ощущение, что первое, и ты просто не заметил, что читается только первая строка...
Страницы: 1 2 3 вся ветка
Форум: "Потрепаться";
Текущий архив: 2004.09.05;
Скачать: [xml.tar.bz2];
Память: 0.65 MB
Время: 0.035 c