среда, 7 марта 2007 г.

Меня опередили

Предлагаю вашему вниманию ссылку http://hallvards.blogspot.com/2007/03/review-delphi-2007-for-win32-beta-part_06.html.

Это статья из блога Hallvard Vassbotn.

Собственно, по поводу нововведений в RTL и компиляторе он все сказал. Я обязательно что-то из сказанного им напишу на русском, но все же добавить к его блогу почти нечего :(

вторник, 6 марта 2007 г.

Delphi 2007 (часть III - FastMM)

Введение

О чем речь

Ниже речь пойдет о FastMM - менеджере парамяти для Delphi for win32. Я поделюсь опытом использования данного продукта и покажу, какие можно получать выгоды от него.

Предполагается, что FastMM используется для отладки приложения. Это важно, т.к. FastMM, работающий в режиме отладки, серьезно тормозит выполнение программы.

Версии дельфи, для которых применим материал

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

История FastMM

Насколько я понимаю, данный манагер памяти был алтернативным манагером до Delphi2005 включительно. Т.е. можно было скачать FastMM (он свободный, где брать - см. ниже) и включить его в свой проект, заменив штатный манагер. Начиная с BDS2006 FastMM уже включен в Delphi.

По сравнению с ранее существовавшим манагером FastMM обладает следующими достоинствами:

  1. Он быстрее.
  2. Он предоставляет сервисные функции для отладки и поиска утечек памяти.

Естественно FastMM включается не только в программы, создаваемый разработчиком, но и в саму IDE. Насколько я понимаю одной из причин резкого ускорения работы IDE при переходе от BDS2005 к BDS2006 был именно FastMM.

Проблемы

Проблема в том, что:

  1. В Delphi FastMM включается только как манагер памяти и как упрощенный поисковик утечек памяти.
  2. В Delphi в настоящий момент полностью отсутствует документация по поводу FastMM (есть соответствующий репорт - http://qc.codegear.com/wc/qcmain.aspx?d=27105, который уже открыт автором FastMM).

При этом никто не машает скачать полную версию FastMM и заменить ею "штатный" FastMM, который есть в Delphi, настроив заменяющий FastMM таким образом, чтобы получать максимальную выгоду от сервисных функций в процессе отладки.

Использование FastMM

Где брать

FastMM хостится на http://www.sourceforge.net. Вот точная ссылка на страницу проекта: http://sourceforge.net/projects/fastmm.

Далее идете по ссылке Download FastMM. и скачиваете версию 4.x. В настоящий момент последней версией является 4.78.

Как устанавливать

Устанавливать собственно и не надо ничего. Есть три файла, которые вам необходимы:

  1. FastMM4.pas
  2. FastMM4Messages.pas
  3. FastMM4Options.inc

Кладете их в каталог проекта (или в путях, прописанных в Library Path в настройках Delphi) и подключаете первым модулем проекта FastMM4.

В случае, если используются runtime пакеты, то FastMM4, естественно не нужно подключать в пакеты - только в главное приложение.

NB Как использовать FastMM для DLL я не знаю, ибо не разбирался. Но в файле FastMM4Options.inc есть очень много комментариев по поводу настройки FastMM. Скорее всего там можно выяснить этот вопрос.

Настройка FastMM

FastMM настраивается посредством опций условной компиляции, задаваемых в файле FastMM4Options.inc. Опции снабжены подробными комментариями. Я для своих задач сделал следующие изменения:

  1. Убрал комментарии для опций UseRuntimePackages, FullDebugMode, ClearLogFileOnStartup.
  2. Закомментировал опцию RequireDebuggerPresenceForLeakReporting.

NB При использовании FastMM с опцией FullDebugMode в каталоге проекта должна быть библиотека FastMM_FullDebugMode.dll, которая есть в поставке FastMM как в виде исходников, так и в виде скомпилированного файла. Подробнее см. каталог FastMM478.zip \FullDebugMode DLL.

Настройки проекта

При возникновении нештатных ситуаций FastMM показывает стек вызовов, приведший к ошибке. Для того, чтобы стек вызовов содержал имена функций и строк в исходном коде нужно в параметрах проекта (и runtime пакетов, если они используются) на закладке Linker в секции Map File выставить опцию Detailed.

Пример использования в целях получения стека вызовов, приведшего к утечке памяти

Цель примера показать, что в стеке вызовов, приведшего к утечке памяти будут методы TMyClass.Execute() и TMyClass.fProcess() с точным указанием номера строки исходного кода.

program Project1;
{$APPTYPE CONSOLE}
uses
FastMM4,Classes,SysUtils;
type
TMyClass = class
public procedure Execute();
strict private procedure fProcess();
end;
procedure TMyClass.Execute();
begin
fProcess();
end;
procedure TMyClass.fProcess();
var
L: TList;
begin
L := TList.Create();
end;
var
MC: TMyClass;
begin
MC := TMyClass.Create();
try
MC.Execute();
finally
MC.Free();
end;
end.

Еси выполнить данную программу, то, во-первых, при завершении программы будет выведено сообщение о том, что были утечки, во-вторых, в каталоге программы будет создан файл Project1_MemoryManager_EventLog.txt, в котором будет представлена более подробная информация об утечке памяти.

В частности будет представлена следующая информация:


Stack trace of when this block was allocated (return addresses):
402DBE [system.pas][System][System.@GetMem][2648]
4036EF [system.pas][System][System.TObject.NewInstance][8824]
40399A [system.pas][System][System.@ClassCreate][9489]
403724 [system.pas][System][System.TObject.Create][8839]
403A08 [system.pas][System][System.@AfterConstruction][9537]
414935 [E:\temp\_Borland\FieldTest\01\Project1.dpr][Project1][Project1.TMyClass.fProcess][18]
41491B [E:\temp\_Borland\FieldTest\01\Project1.dpr][Project1][Project1.TMyClass.Execute][12]
4152FD
794589A5 [ProcessIdToSessionId]
The block is currently used for an object of class: TList

Видно, что здесь, во-первых, указан класс, объект которого "утек", во-вторых, указан стек вызовов, приведший к утечке.

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

NB В какой-то момент может показаться ошибкой, что в стек иногда попадают лишние методы. Я не силен в архитектуре возбуждения исключений, поэтому могу только передать слова автора FastMM: "Я пользовался функцией построения стека, которая реализована в JEDI". От себя замечу, что именно этой функцией пользуется сама IDE в BDS2006 и Delphi2007. Наверное, стоит спокойно относится к лишним методам - лишь бы нужные методы не пропадали.

Пример использования в целях получения стека вызовов, приведшего к вызову метода удаленного объекта

Такой функционал - еще одна сервисная функция, предоставляемая FastMM.

В отладочном режиме (т.е. если включена опция условной компиляции FullDebugMode) FastMM при удалении объекта "портит" память, занимаемую ранее объектом, таким образом, что при следующей попытке вызывать виртуальный метод удаленного объекта FastMM возбуждает исключение.

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

Ниже представлен пример отслеживания момента повторного удаления объекта (деструктор тоже виртуальный метод).

program Project1;
{$APPTYPE CONSOLE}
uses
FastMM4;
type
TMyClass = class
end;
var
MC: TMyClass;
procedure Proc1;
begin
MC := TMyClass.Create();
end;
procedure Proc2;
begin
MC.Free();
end;
procedure Proc3;
begin
MC.Free();
end;
begin
Proc1;
Proc2;
Proc3;
end.

Запустите проект.

Во-первых, вы получите сообщение о том, что была попытка вызывать виртуальный метод удаленного объекта.

Во-вторых, в файле Project1_MemoryManager_EventLog.txt можно посмотреть:

  1. Стек вызовов при создании объекта.
  2. Стек вызовов при удалении объекта.
  3. Стек вызовов при попытке вызывать виртуальный метод объекта (в текущем примере это тот же деструктор).

ИМХО весьма полезно может быть.

Заключение

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

понедельник, 5 марта 2007 г.

Я научился форматировать исходный текст

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

Здесь http://www.delphidabbler.com/software?id=pash&mid=2 расположена удобная утилита для этого. Да и вообще - весь сайт также интересен.

Так что в будущем будут посты только с правильным форматированием текста.

Обратная связь

Уважаемые читатели!

Если у вас есть вопросы, то, пожалуйста, посылайте мне их на почту timokhov@gmail.com. Не нужно задавать вопросы в комментариях к постам. Комментарии (как я думаю) существуют для высказывания своего мнения по поводу приведенной новости.

Я постараюсь обработать данные вопросы и запостить, если что-то будет интересное.

Спасибо за понимание.

Пофиксен старый баг

Всегда приятно, когда видишь, что баг, которому более 3 лет, вот так просто взяли и пофиксили.
Речь об этой ошибке http://qc.codegear.com/wc/qcmain.aspx?d=3793
Мои поздравления автору репорта, Алексею Вукулову aka Vuk!!!

Delphi 2007 (часть II - строковые функции)

Тема

В Delphi 2007 оптимизированы следующие строковые функции:

  1. UpperCase
  2. LowerCase
  3. CompareStr
  4. StrLen
  5. _LStrCmp

Мои исследования

Т.к. я чаще всего пользуюсь сравнением строк (оператор стравнения), то мне наиболее интересно было посмотреть разницу выполнения функции _LStrCmp (именно она в конце концов вызывается при сравнении двух строк if S1 = S2 then ...).

Построив свой первый тест производительности я был удивлен (огорчен), что в BDS 2006 и Delphi 2007 выполнение теста сопостовимо по времени.

Тут я подумал, что не может быть такого - процедуру переписали (вроде это кто-то делал из проекта fastcode - точно я не в курсе ибо не интересуюсь данным проектом), а скорость примерно та же.

Поэтому я полез в исходники и обнаружил, что оптимизация проведена для определенных случаев. Скорость выполнение операции сравнения строк повысилась в случае:

  1. Сравнения строк, если одна (или обе) из них пустая.
  2. Сравнение строк, которые отличаются первым символом.

Я построил еще один тест. Суть теста 10^9 сравнений случайных строк длины 10 со случайной строкой такой же длины.

{$o+}{$r-}{$q-}
program StringFunctionsTest3;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
const
cLen = 1000000;
cStrLen = 10;
cTests = 1000;
var
I,J: Integer;
A: array [0..cLen-1] of String;
PF, PC1, PC2: TLargeInteger;
S: String;
begin
QueryPerformanceFrequency(PF);
for I := 0 to cLen - 1 do
begin
A[I] := '';
for J := 0 to cStrLen-1 do
A[I] := A[I]+Chr(32+Random(60));
end;
S := A[cLen-1];
QueryPerformanceCounter(PC1);
for J := 0 to cTests - 1 do
for I := 0 to cLen - 1 do
if A[I] = S then
Break;
QueryPerformanceCounter(PC2);
WriteLn(Format('%.4f', [(PC2-PC1)/PF]));
ReadLn;
end.
По результатам проверки в BDS 2006 и Delphi 2007 обнаружено ускорение от 30% до 50%.

Также я провел замеры скорости выполнения при сравнении строк, когда одна из них пустая. Также обнаружено ускорение от 30% до 50%.

Данная доработка не может не радовать ибо, во-первых, среда в целом будет работать быстрее, во-вторых, наши с вами программы будут работать быстрее.

воскресенье, 4 марта 2007 г.

Delphi 2007 (часть I)

Что это

Как вы знаете скоро выходит новая версия Delphi2007 for win32. Теперь данный продукт разрабатывается фирмой CodeGear, которая была образована где-то в конце прошлого года на основе подразделения фирмы Borland, которое ранее занималось разработкой Delphi.

Так получилось, что я был в конце января с.г. приглашен в команду тестеров данного продукта. Неделю назад мне было разрешено сообщить некоторую информацию о выходящем продукте.

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

Мой план

Меня уполномочили доносить инфу по поводу Delphi 2007 до России. Но я с огномным удивлением узнал, что про BDS 2006 в России также знаю не очень много. При таком раскладе говорить о Delphi 2007 и его преимуществах перед BDS 2006 глупо - ибо BDS 2006 знаю не особо много людей.

Поэтому я сделаю вольность и буду говорить об обих продуктах сразу, акцентируя внимание на то, что сделано дополнительно в Delphi 2007.

Итог

Пока все :) Нужно еще составить нормальный план изложения. Заходите завтра :)

Доп. материалы

Сами понимаете, что я не один, кто в блогах будет освещать Delphi 2007. Возможно, что я буду один из немногих, кто делает это на русском языке. Однако существует достаточно много источников на английском языке. Я буду стараться собирать ссылки на такие блоги.

Список того, что я нашел к текущему моменту:
  1. http://hallvards.blogspot.com/