![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Чем писать лог? [D7, XP]
Б © (2009-10-13 17:58:00)Здрасти!
Работаю над логом. (Записывать много чего придёться)
Встал выбор: каким образом работать с текстовым файлом.
1 способом, через Pascal'евские - Assign, WriteLn, Reset... (Var File: Text)
2 способом, через Windows'ие - CreateFile, WriteFile... (Var File: LongWord)
Пока выбрал 1-й. (Но что-то, говорят, для логов не пойдёт)
Всё таки: какой способ лучше и быстрее?
А может есть альтернативы?
Германн (2009-10-20 01:51:00) [1]Начиная с "DVM © (18.10.09 14:24) [33]"
начался холивар, который продолжил холивар на Королевстве, и которого так жаждал автор сабжа.
Ну почему-бы автору не задать сей вопрос на www.sources.ru? Там к холиварам вроде нормально относятся.
Anatoly Podgoretsky (2009-10-19 22:57:00) [2]> DVM (19.10.2009 20:17:50) [50]
Writeln ой как не просто, начнем с того, что нет процедуры Writeln, это компьютерная магия.
Кроме того зачем сравнивать низкоуровневый вывод с высокоуровневым, когда за сценой ой как много чего справлено, избавляя от необходимости думать об преобразованиях. Можно сравнивать например с Бейсиком или некоторыми другими языками, которые имеют встроеные средства ввода/вывода.
WriteLn(F, Integer, Float, Boolean, DateTime, string) и все это одновременно в одном вызове без необходимости преобразования в текстовый формат, плюс есть и небольшие возможности форматирования вывода, что не мешает внешнему форматированию. Плюс еще и буферизация и возможность расширения.
Но есть некоторые ограничения, по режимам открытия файла, по Юникоду, ведь "функции" более 30 лет.
Leonid Troyanovsky (2009-10-19 20:34:00) [3]
> DVM © (19.10.09 20:17) [50]
> Да нет там огреха.
> Очевидно, что если организовать/задействовать буферизацию
> WriteFile/TFileStream то как минимум
Дык, тут и огрех, чего у ж там далее.
Сравнивать стоит сопоставимое.
> задействовать буферизацию WriteFile/TFileStream то как минимум
Ясенное дело, что сравняются "как минимум", бо выше - overhead.
--
Regards, LVT.
DVM (2009-10-19 20:17:00) [4]
> Leonid Troyanovsky © (19.10.09 18:58) [49]
> а мы постараемся найти огрех.
Да нет там огреха. Понятно, что я сравнивал "просто Writeln" с "просто WriteFile" и TFileStream.Write(). Только вот "просто Writeln" оказался "просто буферизованный Writeln".
Большинство ведь и не догадываются о том, что Writeln использует хитрую буферизацию и внутренности Writeln как правило мало кем изучаются и Writeln рассматривается как нечто совсем простое как 2 копейки. Ан нет оказывается, Writeln не так прост. Я вот сам заблуждался.
Очевидно, что если организовать/задействовать буферизацию WriteFile/TFileStream то как минимум они сравняются.
Leonid Troyanovsky (2009-10-19 18:58:00) [5]
> DVM © (19.10.09 00:47) [47]
> > У тебя тесты какие-то неправильные.
> Может поделишься правильными?
Ну, ты ж сам все правильно объяснил.
Внизу лежит WriteFile, сверху - overhead.
Там же еще парсинг строк и т.п.
Сравнивать можно, скажем, WriteFile vs memory mapped file,
хотя, наверное, и это мну не очень интересно.
Проще, наверное, если б ты показал сравнения
(у тебя, IMHO, д.б. где-то под рукой),
а мы постараемся найти огрех.
--
Regards, LVT.
sniknik (2009-10-19 01:08:00) [6]> Может поделишься правильными?
лучше "правильным" компьютером с новыми дисками которым программная буферизация только мешает... (адрес для "дележки" в личку ;о) )
DVM (2009-10-19 00:47:00) [7]
> Leonid Troyanovsky © (18.10.09 23:46) [46]
> У тебя тесты какие-то неправильные.
Может поделишься правильными? И мы поучимся.
Leonid Troyanovsky (2009-10-18 23:46:00) [8]
> DVM © (18.10.09 16:06) [39]
> Writeln почти в 2 раза обгоняет Windows.WriteFile и соответственно
> TFileStream.
У тебя тесты какие-то неправильные.
--
Regards, LVT.
Игорь Шевченко (2009-10-18 21:19:00) [9]DVM © (18.10.09 20:42) [44]
Как ты понимаешь - кому что надо, кому надо подробный лог для диагностики (а для чего еще лог нужен?), кому надо быстро. Для "быстрого" протоколирования мы использовали отдельный процесс, которому посылали сообщения о необходимости занесения в протокол тех или иных данных, натурально, у этого процесса был достаточный буфер, чтобы он не захлебывался при приеме сообщений с достаточно интенсивной скоростью, разумеется, было управление файлами, чтобы текущий протокол по достижении нужного размера/количества записей отключался и сбрасывался в базу данных/архив, а запись при этом велась в другой файл, ну и так далее.
Только сложно это - мы использовали для протоколирования работы нескольких связанных процессов, Event log нам не понравился, уж больно неудобно делать его пост-обработку.
DVM (2009-10-18 20:42:00) [10]
> Игорь Шевченко © (18.10.09 19:00) [42]
> Для лога, я считаю, гораздо удобнее в ряде случаев использовать
> не буферизованный ввод/вывод, а закрытие файла после каждой
> записи
Только у этого способа есть один недостаток - уж слишком сильно замедляет программу при интенсивном логгировании.
Eraser (2009-10-18 20:04:00) [11]для отладки использую
unit ROMLog;
interface
uses
Windows, SysUtils;
function AppendLog(const AMsg: string): Boolean;
var
_csROMLog: TRTLCriticalSection;
implementation
function AppendLog(const AMsg: string): Boolean;
var
fText: TextFile;
sFileName, sText: string;
begin
Result := False;
try
sFileName := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
if not DirectoryExists(sFileName + 'Logs') then
MkDir(sFileName + 'Logs');
sFileName := sFileName + 'Logs\' + FormatDateTime('yyyy_mm', Now) +
'_rom_log.txt';
except
Exit;
end;
EnterCriticalSection(_csROMLog);
try
AssignFile(fText, sFileName);
if FileExists(sFileName) then
Append(fText)
else
Rewrite(fText);
try
sText := FormatDateTime('dd-mm-yyyy_hh:nn:ss', Now) +
'#T:' + AMsg;
Writeln(fText, sText);
finally
CloseFile(fText);
end;
Result := True;
finally
LeaveCriticalSection(_csROMLog);
end;
end;
initialization
InitializeCriticalSection(_csROMLog);
finalization
DeleteCriticalSection(_csROMLog);
end.
если лог нужен для функционала, то лучше использовать другой подход.
Игорь Шевченко (2009-10-18 19:00:00) [12]Для лога, я считаю, гораздо удобнее в ряде случаев использовать не буферизованный ввод/вывод, а закрытие файла после каждой записи. В этом случае удобно а) смотреть лог работающей программы б) в случае ошибки в программе все данные лога будут на диске (а не в текстовом буфере), что в ряде случаев упрощает диагностику.
Кстати, конструкция
AssignFile(F, 'foo');
if FileExists('foo') then
Append(F)
else
Rewrite(F);
Лмается на файлах больше двух гигагбайт. Но я не пишу логи в несколько гигабайт - уж больно с ними потом неудобно работать :)
DVM (2009-10-18 16:33:00) [13]
> Sapersky (18.10.09 16:20) [40]
>
> WriteLn буферизованный.
Да, так и есть. Если писать довольно большими кусками он начинает чуть отставать от Windows.WriteFile
Sapersky (2009-10-18 16:20:00) [14]WriteLn буферизованный. Если ещё буфер задать 2-4 кб вместо стандартных 128 байт (SetTextBuf), будет ещё быстрее.
Я в той ветке на Королевстве выкладывал результат сравнения буферизованного (хотя и не конкретно WriteLn) и небуферизованного методов - разница в 3.5 раза.
DVM (2009-10-18 16:06:00) [15]
>
> > Вряд ли. Где тесты на сравнение и результаты?
>
> Без проблем щас организуем.
Провел сравнительное тестирование TextFile/Writeln , TFileStream и Windows.WriteFile.
Результаты оказались довольно неожиданными для меня.
Writeln почти в 2 раза обгоняет Windows.WriteFile и соответственно TFileStream.
Самое удивительное, что Writeln сводится к той же Windows.WriteFile
Так что насчет скорости я был не прав.
DVM (2009-10-18 15:25:00) [16]
> Выдает:
>
> ---------------------------
> Project1
> ---------------------------
> Error: 105:I/O error 105(Операция успешно завершена/Этот
> семафор более не принадлежит использовавшему его процессу)
> ---------------------------
> OK
> ---------------------------
>
> Ерунда какая то.
Хотя нет, извиняюсь, не заметил что в твоем коде Reset(f); а не Rewrite;
DVM (2009-10-18 15:14:00) [17]
> qwer_qwer (18.10.09 14:53) [34]
> Если это не преимущество и недостаток, тогда зачем это упоминать?
> Для красного словца?
Я не упоминал.
> Пожалуйста. В чём проблема-то? В неумении?
Да насчет отсутствующего диска я погорячился, но хорошо, вот другой пример, файл c:\1.txt имеет атрибут только чтение (или нет доступа со стороны файловой системы)
Твой код:
]
procedure TForm1.btn1Click(Sender: TObject);
var
f: TextFile;
begin
try
AssignFile(f,'c:\1.txt');
Reset(f);
write(f, 'test');
CloseFIle(f);
except
on E: EInOutError do
ShowMessage('Error: '+IntToStr(E.ErrorCode)+':'+E.Message+
'('+SysErrorMessage(GetLastError)+'/'+SysErrorMessage(E.ErrorCode)+')');
end;
end;
Выдает:
---------------------------
Project1
---------------------------
Error: 105:I/O error 105(Операция успешно завершена/Этот семафор более не принадлежит использовавшему его процессу)
---------------------------
OK
---------------------------
Ерунда какая то.
Правильный код на TFileStream:
procedure TForm1.btn2Click(Sender: TObject);
var
Stream: TFileStream;
s: string;
begin
s := 'test';
Stream := TFileStream.Create('c:\1.txt', fmOpenWrite);
try
Stream.Write(s[1], Length(s) * SizeOf(Char));
finally
Stream.Free;
end;
end;
выдает
---------------------------
Project1
---------------------------
Cannot open file "c:\1.txt". Отказано в доступе.
---------------------------
ОК
---------------------------
> Вряд ли. Где тесты на сравнение и результаты?
Без проблем щас организуем.
Плохиш (2009-10-18 15:13:00) [18]
> qwer_qwer (18.10.09 14:53) [34]
> Вообще-то на этих форумах технические специалисты, а не
> гуманитарии с любовью к красивым словам
Экма :-) "наивный чукотский мальчик" :-))
qwer_qwer (2009-10-18 14:55:00) [19]Особенно красиво звучит ничем не обоснованное -
> можно продолжать бесконечно и во всех случаях толковой информации
> о том что же произошло от этих функций не получишь.
qwer_qwer (2009-10-18 14:53:00) [20]
> Вот именно, это даже не преимущество. Так что преимуществ
> у паскалевских методов работы с файлами нет вообще. Анахронизм
> это.
Если это не преимущество и недостаток, тогда зачем это упоминать? Для красного словца? Вообще-то на этих форумах технические специалисты, а не гуманитарии с любовью к красивым словам.
> Ну обработай мне исключение, которое возникает при доступе
> паскалевской функции к дисководу в котором нет диска. Или
> когда отсутствуют права на доступ к файлу, или ... эти или
> можно продолжать бесконечно и во всех случаях толковой информации
> о том что же произошло от этих функций не получишь. Хошь
> обрбатывай, хошь не обрабатывай.
Пожалуйста. В чём проблема-то? В неумении?
procedure TForm1.Button1Click(Sender: TObject);
var
f: TextFile;
begin
try
AssignFile(f,'a:\1.txt');
Reset(f);
CloseFIle(f);
except
on E: EInOutError do
ShowMessage('Îøèáêà '+IntToStr(E.ErrorCode)+':'+E.Message+
'('+SysErrorMessage(GetLastError)+'/'+SysErrorMessage(E.ErrorCode)+')');
end;
end;
> Попробуй писать очень интенсивно и много - разница налицо.
Вряд ли. Где тесты на сравнение и результаты?
> Задачи никакой не ставилось. А потокобезопасный лог - сплошь
> и рядом треуется.
Вот когда он потребуется, тогда и потребуется отдельное обсуждение для конкретной задачи.
> Такого, какого позволяет файловая система, не меньше.
А если точнее? В Мб,Гб, Тб?