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

Вниз

критика кода DMClient   Найти похожие ветки 

 
nikkie ©   (2004-08-12 11:45) [0]

тема, родившаяся в недрах (со 114-го по 128-й примерно пост)
http://delphimaster.net/view/14-1091941670/

если у кого есть желание выступить с конструктивными предложениями или просто поругать код, милости просим сюда.


 
Sandman25 ©   (2004-08-12 11:48) [1]

AssignFile и Rewrite рулят.
CreateFile может стать deprecated в новых версиях виндоус :)


 
Думкин ©   (2004-08-12 11:49) [2]

Можно чтобы "Написать ответ" было внизу окна всегда или по желанию?
А то иногда прыгать приходится по ветке и набирать корзину для ответа, а потом уже отвечать скопом.
Или никак?


 
nikkie ©   (2004-08-12 11:50) [3]

по поводу AssignFile и т.д. мы вроде разобрались - это личная неприязнь к этим функциям у Fay. теперь хотелось бы разъяснить такой момент.

>Fay
>А вычисление количества строк через ReadLn в цикле - просто шедевр.

какие есть альтернативы?


 
Sandman25 ©   (2004-08-12 11:50) [4]

[2] Думкин ©   (12.08.04 11:49)

Запускай 2 клиента :)


 
Anatoly Podgoretsky ©   (2004-08-12 11:52) [5]

nikkie ©   (12.08.04 11:45)  
Обычно этот процесс называют - порка <наименование>, эта терминология уже прижилась.


 
Danilka ©   (2004-08-12 11:53) [6]

[3] nikkie ©   (12.08.04 11:50)
> какие есть альтернативы?

Например, читать файл посимвольно и подсчитывать #13#10.

[4] Sandman25 ©   (12.08.04 11:50)
Попробуй, не запускается. :))


 
Sandman25 ©   (2004-08-12 11:55) [7]

[6] Danilka ©   (12.08.04 11:53)

Упс. Предыдущая версия запускалась. Зря я экзешник не переименовал при апгрейде, пригодился бы.


 
Anatoly Podgoretsky ©   (2004-08-12 11:59) [8]

nikkie ©   (12.08.04 11:50) [3]
Нет альтернативы

Danilka ©   (12.08.04 11:53) [6]
Работать с текстовыми файлами как с двоичными конечно можно, но не кошерно.


 
nikkie ©   (2004-08-12 12:02) [9]

>Думкин
>Можно чтобы "Написать ответ" было внизу окна всегда или по желанию?
идея понятна, можно подумать на эту тему.

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

о программе
http://schachspieler.narod.ru/dmclient.html
скачать исходники можно здесь:
http://prdownloads.sourceforge.net/dmclient/dmclient_2.1.2_src.zip?download


 
nikkie ©   (2004-08-12 12:07) [10]

>Anatoly Podgoretsky
хорошо, назовем это:
"публичная порка меня родимого"
с хитрым прицелом...

>Sandman25
>Запускай 2 клиента :)
есть проще и удобнее вариант - notepad или какой там твой любимый текстовый редактор в качестве второго окна.


 
Piter ©   (2004-08-12 12:27) [11]

Имхо, код DMClient"а очень грамотный. Придраться всегда можно, но если кто из критикующих представит код более понятный - прошу выложить, я с удовольствием посмотрю

P.S. Не забывайте, Nikkie - мастер, хоть и не засвеченный, поэтому туфты в коде не напишет :)


 
Piter ©   (2004-08-12 12:27) [12]

nikkie ©   (12.08.04 12:07) [10]
есть проще и удобнее вариант


а еще проще и удобнее - сделать как я сделал в клиенте


 
Fay ©   (2004-08-12 12:42) [13]

2 nikkie ©   (12.08.04 11:50) [3]


function GetLineCount(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;


 
Fay ©   (2004-08-12 12:50) [14]

2 Anatoly Podgoretsky ©   (12.08.04 11:59) [8]
Не кошерно работать с многозадачной, имеющей продвинутую систему прав, ОС так же, как под "ДОСкой". А вещи типа "если файл есть, то открыть, иначе - создать" пишутся одной функцией CreateFile. Но говорить об это не принято. Идиотизм.


 
Fay ©   (2004-08-12 12:59) [15]

2 Piter ©   (12.08.04 12:27) [11]
Глянь на GetLastQuestionTimeStamp.

З.Ы.
В целом - программа ничего. Просто не нравится. Особенно работа с текстом и файлами.


 
Anatoly Podgoretsky ©   (2004-08-12 13:03) [16]

Fay ©   (12.08.04 12:50) [14]
Можно, но придется дублировать работу, которая уже проделана разработчиками Паскаля. Если есть желание то почему бы и нет.


 
nikkie ©   (2004-08-12 13:05) [17]

я так и думал, что предложишь через FileMapping сделать. наверное, быстрее получится, интересно проверить насколько. думаю, что пользователь не заметит разницы. есть другое место, где гораздо более серьезен вопрос производительности - SaveNewQuestions. к сожалению, так, как сейчас хранится ускорить существенно не получится (хотя к моему удивлению все равно работает довольно шустро, хотя и видна разница между тем, когда есть обновления и когда их нет - подтормаживание в пределах секунды). надо было бы сделать хранение тем в обратном порядке, можно было бы сделать быстрее.

>Идиотизм.
ну зачем так... кому-то может вопрос кросс-платформенности важнее.


 
Fay ©   (2004-08-12 13:08) [18]

2 Anatoly Podgoretsky ©   (12.08.04 13:03) [16]
Это не дублирование. Почти ничего общего. А вот сделать раз в 20 быстрее - почему бы и нет? С тому же, использовать CreateFile под Windows - нормально и правильно.


 
Fay ©   (2004-08-12 13:09) [19]

2 nikkie ©   (12.08.04 13:05) [17]
Не скинешь ссылочку на кроссплатформенный MSHTMP_tbl.pas ? Очень надо 8)


 
Danilka ©   (2004-08-12 13:19) [20]

[18] Fay ©   (12.08.04 13:08)
> А вот сделать раз в 20 быстрее - почему бы и нет?

Чем тестировал? Откуда такие результаты, что через CreateFile в 20 раз быстрее чем через по-обычному, для паскаля, способу?


 
nikkie ©   (2004-08-12 13:24) [21]

>раз в 20 быстрее
ой ли? сейчас будем проверять...

>GetLastQuestionTimeStamp
что там не понравилось?

>Не скинешь ссылочку на кроссплатформенный MSHTMP_tbl.pas ? Очень надо 8)
я иронию уловил... тебя не удивляет, что работа с сервером вынесена DMCServer.pas, работа с файлами собрана в DMCStorageFile.pas, за каким-то лешим еще сделан DMCStorage.pas, а не навалено все в Main.pas? в той ветке мы обсуждаем возможность создания клиента в виде web-сервера или news-gate. ты думаешь, что этот код не мог бы быть повторно использован для такого приложения, будучи откомпилированным FPC или Kylix?

так что MSHTML_TLB.pas не абсолютно необходим... и потом, ты ведь не только меня ругаешь, а всех, использующих AssignFile и co.


 
Fay ©   (2004-08-12 13:26) [22]

2 Danilka ©   (12.08.04 13:19) [20]
Присылай пример. Сравним. А то так можно кому хочешь сказать "У мене типа с пол-метра, не меньше".

2 nikkie ©   (12.08.04 13:05) [17]
MSHTMP_tbl.pas следует читать как MSHTML_tbl.pas


 
Danilka ©   (2004-08-12 13:31) [23]

[22] Fay ©   (12.08.04 13:26)
У меня нет примера. Но видимо у тебя есть, раз ты так смело говоришь, что в 20 раз быстрее. Поэтому я и хотел узнать, откуда ты взял эту цифру, как тестировал.


 
Danilka ©   (2004-08-12 13:32) [24]

[21] nikkie ©   (12.08.04 13:24)
В качестве оффтопика, у тебя под какую версию дельфи клиент писан?


 
Fay ©   (2004-08-12 13:35) [25]

Это цифра из сравнения способов вычисления количества строк в файле. А TDMCStorageFile.GetLastQuestionTimeStamp думаю раз в 100 можно ускорить. Если не больше.


 
Fay ©   (2004-08-12 13:37) [26]

2 Sandman25 ©   (12.08.04 11:48) [1]
Надо иметь неслабое здоровье, чтобы дожить до этого.


 
nikkie ©   (2004-08-12 13:56) [27]

>GetLastQuestionTimeStamp думаю раз в 100 можно ускорить
каким образом? пиши свою версию, сравним.


 
Fay ©   (2004-08-12 13:57) [28]

ОК


 
Sandman25 ©   (2004-08-12 13:58) [29]

[26] Fay ©   (12.08.04 13:37)

Ну, если Вы подрабатываете в MS главным идеологом, спорить не буду :)


 
nikkie ©   (2004-08-12 13:58) [30]

>Danilka
>под какую версию дельфи клиент писан?
исходники компилируются под D5-D7 при условии, что установлены Indy и EmbeddedWB.


 
Anatoly Podgoretsky ©   (2004-08-12 14:07) [31]

Danilka ©   (12.08.04 13:19) [20]
Проверка скорости загрузки списка строк операциями ReadLn и потоковыми, показывала неодназначные результаты, раз на раз не приходился. И никакими 20 разами и близко не пахнет. Красота работы со строками у ReadLn большая, а когда оказывается нужным сделать например такое ReadLn(F, IntVar, FloatVar, BooleanVar, DateVar, SteVar) то особо проявляется, сложность создания такого же но не средствами ReadLn ни как не может окупить даже возможное некоторое замедление.
Ну и самое простое если кому то не нравится поддержка текстовых и типизированых файлов в Паскале, а есть желание разработать свое, то это его право, было бы желание, а запрета нет.


 
cyborg ©   (2004-08-12 14:08) [32]

На Фрипаскале написал:

Program test2;

Uses SysUtils;

function GetCPUTick: int64; assembler;
asm
 db 0fh,31h;
end;

Function GetNumStrings(Var 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;

Var
 Time : Int64;
 F : File;
 P : Pointer;
 Size : Longint;
 NumStrings : Longint;
BEGIN
 Time:=0;

 if ParamCount>0 then
 if FileExists(ParamStr(1)) then
 begin
   Time:=GetCPUTick;

   AssignFile(F,ParamStr(1));
   Reset(F,1);
   Size:=FileSize(F);
   GetMem(P,Size);
   
   BlockRead(F,P^,Size);
   NumStrings:=GetNumStrings(P, Size);
   
   FreeMem(P,Size);
   CloseFile(F);
   
   Time:=GetCPUTick-Time;
 end;

 WriteLn("File: ",ParamStr(1));
 WriteLn("Number of strings - ",NumStrings);
 WriteLn("Speed CPU ticks - ",Time);
 WriteLn;
 WriteLn("Press ENTER:");
 ReadLn;
 
END.


Результат по файлу этого же исхождника:


File: test2.pas
Number of strings - 60
Speed CPU ticks - 544590

Press ENTER:


Напиши чтобы в 20 раз быстрее было?


 
Sandman25 ©   (2004-08-12 14:10) [33]

[32] cyborg ©   (12.08.04 14:08)

А если файл имеет размер 10Гб. Так и будем GetMem(FileSize) юзать?


 
Anatoly Podgoretsky ©   (2004-08-12 14:14) [34]

cyborg ©   (12.08.04 14:08) [32]
Писать по требованию надо, что бы в 20 раз медленнее было!!! Такого было утверждение. Где у тебя проверка с ReadLn? Я к тому же не заостряю внимание на том, что код неправильный, разделитель строк не #10, а #13#10.


 
cyborg ©   (2004-08-12 14:16) [35]


> [34] Anatoly Podgoretsky ©   (12.08.04 14:14)

проверка разделителей как раз правильна, это в ДОСе было только #13#10, сейчас достаточно искать только #10, оно и в таком и в таком формате разделителя присутствует.


 
cyborg ©   (2004-08-12 14:19) [36]


> [33] Sandman25 ©   (12.08.04 14:10)

10 гигов не каждая файловая система держит. Я знал, что акой пример приведут, достаточно переделать на чтение по частям, функция таже, только несколько раз вызывать с новыми читаемыми данными и складывая реультат, к примеру по 4 килобайта достаточно для экономии памяти?


 
nikkie ©   (2004-08-12 14:23) [37]

тестовая программа:
program LineCount;

{$APPTYPE CONSOLE}

uses
 SysUtils, Windows;

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;

type
 TGetLineCountFunc = function (const cFileName : string) : Integer;
const
 TEST_NUM   = 100;
 TEST_FILE = "C:\temp\list.txt";

procedure Test(f: TGetLineCountFunc; const FileName: string; Desc: string);
var
 dwStart, dwEnd: DWORD;
 i: integer;
begin
 dwStart := GetTickCount;
 for i := 0 to TEST_NUM do begin
   f(FileName);
 end;
 dwEnd := GetTickCount;
 Writeln(Desc, dwEnd - dwStart, " ticks spent");
end;

begin
 Test(GetLineCountStd, TEST_FILE, "Std:");
 Test(GetLineCountFay, TEST_FILE, "Fay:");
end.


тестовые файлы - это списки тем из моего архива за год и 3 месяца, которые существует клиент. те самые файлы, для которых эта функция и вызывается реально.

"Потрепаться" (размер 5181701 байт, 16256 строк).
Std:11687 ticks spent
Fay:1266 ticks spent

"Основная" (размер 6342060 байт, 20328 строк).
Std:14328 ticks spent
Fay:1532 ticks spent

резюме: работает почти в 10 раз быстрее, 0.01 секунды вместо 0.1 секунды.

btw, если в файле последний символ 0x12, в твоей функции все пучком будет?


 
Sandman25 ©   (2004-08-12 14:25) [38]

[36] cyborg ©   (12.08.04 14:19)

Вполне.


 
Anatoly Podgoretsky ©   (2004-08-12 14:26) [39]

nikkie ©   (12.08.04 14:23) [37]
Упрости Readln(F);
и поменяй местами

Test(GetLineCountStd, TEST_FILE, "Std:");
Test(GetLineCountFay, TEST_FILE, "Fay:");


 
nikkie ©   (2004-08-12 14:28) [40]

тьфу, не 0x12, а 0x13, конечно.
по-моему строку
if p[1] = #10 then Inc(p);
выкинуть надо, а 0x13 заменить на 0x10.



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

Форум: "Потрепаться";
Текущий архив: 2004.09.05;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.04 c
3-1092293006
stud
2004-08-12 10:43
2004.09.05
не работает такая конструкция


1-1092834503
Erik1
2004-08-18 17:08
2004.09.05
Как прямо записать в структуру TMaps = set of TMap число?


8-1086877591
AvI
2004-06-10 18:26
2004.09.05
Media Plaer на API


1-1093229977
Vilux
2004-08-23 06:59
2004.09.05
TTree и прокрутка


14-1092661715
nasty
2004-08-16 17:08
2004.09.05
hypertext applications





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский