Текущий архив: 2003.06.16;
Скачать: CL | DM;
ВнизКлассы, обьекты,... Найти похожие ветки
← →
Vertex3f (2003-05-30 17:35) [0]У меня частицы (их много) существуют в виде обьекта, а какой будет выигрышь если я их переделаю под запись (record)?
И еще: какова реальная разница между обьектом класса (TObj=class; var Obj:TObj) и обьектом (Obj=object)?
Спасибо...
← →
Юрий Зотов (2003-05-30 18:40) [1]> а какой будет выигрышь если я их переделаю под запись
При идентичных полях и их выравнивании - 4 байта на каждый экземпляр.
> какова реальная разница...
Неясно, что такое object в "Obj=object".
← →
jack128 (2003-05-30 19:51) [2]Юрий Зотов © (30.05.03 18:40)
это в памяти, а в производительности?
я думаю
var Rec:TRec;
begin
...
end;
отличается от
var obj : TMyObject;
begin
obj := Tmyobject.Create;
...
obj.Free;
end;
← →
vuk (2003-05-30 20:06) [3]to jack128:
>это в памяти, а в производительности?
Не уверен на 100%, но в вопросе есть слово "много". Обычно в таких случаях это означает, что элементы создаются динамически, а не статически, как у Вас это сделано для record.
← →
Юрий Зотов (2003-05-30 20:07) [4]Если Вы не собираетесь заводить большое число статических записей, то разница будет примерно на время выполнения FillChar (на каждый экземпляр).
← →
Vertex3f (2003-05-30 20:45) [5]Спасибо
vuk, верно понял. Частицы создаются динамически.
Для меня наиболее важна скорость, поэтому я спрашиваю выигрышь в скорости...
← →
jack128 (2003-05-30 21:04) [6]vuk © (30.05.03 20:06)
оки
var P : ^Rec;
begin
New(p);
...
Dispose(p);
end;
В любом случае я к тому что, имхо, просто выделение памяти(в случае в записями) гораздо быстрее, чем выполнение конструктора,который помимо выделения памяти ещё строит VTM, например...
← →
vuk (2003-05-30 21:04) [7]Если динамичесчки, то практически без разницы. Как уже Юрий Зотов заметил, разница на время выполнения FillChar. Ну, может чуть побольше. Эта разница складывается из того самого FillChar и некоторой дополнительной инициализации для объектных типов. Если вас интересует именно время, можно замерить скорость. Существенная разница будет, скорее всего, только при нескольких миллионах элементов. Стоит ли из-за нескольких миллисекунд жертвовать удобством решать Вам.
← →
vuk (2003-05-30 21:06) [8]to jack128:
>который помимо выделения памяти ещё строит VTM, например...
Сказки это всё. VMT строит компилятор, а не конструктор.
← →
jack128 (2003-05-30 21:19) [9]
> vuk © (30.05.03 21:06
То есть? компилятор строит код. Согласно этому коду при создании объекта заполняется его VMT. Или как?
← →
Ihor Osov'yak (2003-05-30 21:29) [10]VMT - одна на класс. Для екземпляров инициализируется только указатель на эту таблицу.
← →
vuk (2003-05-30 21:31) [11]VMT не заполняются, они существуют с момента загрузки исполняемого модуля. У каждого экземпляра хранится ссылка на свой класс (те самые 4 байта). А сама структура класса содержит указатель на VMT. При инициализации экземпляра дополнительно прописывается только эта ссылка на класс.
← →
Fantasist. (2003-05-30 21:41) [12]
> Как уже Юрий Зотов заметил, разница на время выполнения
> FillChar
А как же вызовы NewInstance, InstanceSize, InitInstance, AfterConstruction? Все они происходят при создании экземпляра класса.
← →
vuk (2003-05-30 21:47) [13]to Fantasist:
>А как же вызовы NewInstance, InstanceSize, InitInstance,
>AfterConstruction? Все они происходят при создании экземпляра
>класса.
Так никто и не спорит. Но я ж говорю - мерять надо... Кстати, померял. Замеры производил при помощи GetTickCount. Разница на 1000000 элементов - 15 миллисекунд (это, правда, зависит от производительности машины). Стоит геморрой свеч? ИХМО нет.
← →
jack128 (2003-05-30 21:48) [14]угу. понятно, спасибо
← →
Юрий Зотов (2003-05-30 22:34) [15]> Fantasist (30.05.03 21:41)
InstanceSize - ни при чем, т.к. на этапе создания вызывается лишь внутри других методов и поэтому ее время входит во время работы этих методов. Вообще же, это очень быстрая функция - она всего лишь возращает одно из полей VMT, заполняемое на этапе компиляции. Остальные функции, вызываемые при динамическом создании:
Потомок TОбъект Запись Разница во времени
-----------------------------------------------
NewInstance GetMem Примерно одинаково
InitInstace - Примерно FillChar
AfterConstruction - Почти ноль (вызов пустой функции)
Как видим, основное время занимает FillChar. Вот и судите сами.
А вообще, чего гадать, когда проще поставить эксперимент?
type
PMyRecord = ^TMyRecord;
TMyRecord = record
FInt: integer;
FBool: boolean;
FStr: string
end;
TMyObject = class
FInt: integer;
FBool: boolean;
FStr: string;
end;
const
N = 1000000;
procedure TForm1.Button1Click(Sender: TObject);
var
T: DWORD;
i: integer;
P: PMyRecord;
begin
Caption := "";
T := GetTickCount;
for i := 1 to N do
begin
New(P);
Dispose(P)
end;
Caption := IntToStr(GetTickCount - T)
end;
procedure TForm1.Button2Click(Sender: TObject);
var
T: DWORD;
i: integer;
O: TMyObject;
begin
Caption := "";
T := GetTickCount;
for i := 1 to N do
begin
O := TMyObject.Create;
O.Free
end;
Caption := IntToStr(GetTickCount - T)
end;
Результаты трехкратных замеров и среднее значение (в миллисекундах):
Объект Запись
235 187
218 172
219 172
-----------
224 177
То есть, для неупакованных записей цикл "создание-уничтожение" в данном случае получился на 21% быстрее. Тот же тест для упакованных записей показал такие результаты: 203, 218, 219 (среднее - 213,3 или на 4,8% быстрее).
Теперь между New и Dispose вставляем строку:
FillChar(P^, SizeOf(TMyRecord), 0);
И получаем:
Неупакованная запись Упакованная запись
219 218
204 218
203 219
----------------------------------------
208,7 (6,8%) 218,3 (2,5%)
Это показывает, что основную разницу дает как раз FillChar.
Ну а выводы делайте сами. Приняв во внимание погрешность самого теста.
← →
nikkie (2003-05-30 22:37) [16]еще один момент. если надо 1000 рекордов, то память под них можно выделить одним куском, имхо должно получиться быстрее.
← →
nikkie (2003-05-30 22:41) [17]уточнение. если строк и ссылок в рекорде нет. и если потом не надо будет часть из этих 1000 записей удалить. короче, так делать можно будет только в каких-то специфичных задачах.
← →
Тих (2003-05-30 23:18) [18]nikkie © (30.05.03 22:41)
Ага, то же самое можно провернуть и для классов - Элджер для повышения производительности предлагает для классов выделять память куском-пулом (в стеке(быстрее) или куче) и переписать конструктор. Правда, речь у него о С++; вот хотелось бы у народа узнать - как это на Delphi реализуется?
← →
Malder (2003-05-30 23:54) [19]Вы, конечно, очень хорошую тему завели, но я принципиально не понимаю, как можно объект переделать в запись (!!!). Здесь речь идет не о скорости, а о логике приложения. Если черный ящик можно реализовать с помощью записей - так и надо делать. Если же он подразумевает какую-нибудь функциональность, то в виде объекта.
← →
Suntechnic (2003-05-31 00:03) [20]Malder © (30.05.03 23:54)
Здесь речь идет не о скорости, а о логике приложения.
Не всегда. Иногда эти понятия пересекаются и исходя из скорости приложения мы меняем логику. Вот Вам типичный пример. Представьте себе графическую систему. Как по-вашему, объект этой системы Point, должен быть ссылочным типом или value-типом?
← →
Malder (2003-05-31 00:10) [21]Suntechnic, да, я согласен с твоим мнением. Но коли мы говорим о Дельфи! О RAD системе, то не стоит заводить такие темы. Бесспорно, иногда скорость - это все. И из-за этого можно сидеть круглые сутки, думаю над тем, как оптимизировать маленький кусок кода. Но в данном случае рекомендую обратиться к ассемблеру, а не к Дельфи, которая совершенно справедливо была нацелена на гигагерцовые процесоры и гигабайтные винчестеры, где удобоваримость кода один из главных показателей (а значит и возможность легкой модифицируемости и т.д.)
← →
Alex Konshin (2003-05-31 08:13) [22]Для интересующихся: у меня в модуле Arrays есть финт с вделением памяти под объекты одним куском. Собственно, в этом есть принципиальное отличие Array от динамических массивов: он выделяет память для объектов, а не для указателей на них.
Как это реализовано можете посмотреть сами:
http://home.earthlink.net/~akonshin/index.htm
Могу еще порекламировать этот юнит: там есть реализации классов массивов объектов с сортировкой и маппингом, т.е. там можно доступаться как по логическому индексу, так и по физическому (сами элементы не перемещаются при сортировке), и можно делать фильтрование, т.е. логически элементов может быть меньше, чем физически. В качестве наглядной демонстрации взгляните еще на модуль ArrayGrids, который может использовать эти массивы в качестве источника данных.
← →
vuk (2003-05-31 10:40) [23]to Тих:
>вот хотелось бы у народа узнать - как это на Delphi реализуется?
У TObject есть метод виртуальный класса NewInstance, который выделяет память под экземпляр.
← →
jack128 (2003-05-31 15:22) [24]тут не давно речь заходила про память и мелькнула такая ссылка, статья про дельфийский менеджер памяти http://rsdn.ru/article/default.asp?Delphi/memmanager.xml
← →
Alex Konshin (2003-05-31 23:29) [25]2vuk: Беда только в том, что у NewInstance нет параметров и нет легального способа сказать ему где и как ее выделять. Поэтому выделить память под объект иначе, чем по GetMem проблематично.
Но у меня это обходится: я передаю адрес массива через ECX. Короче, смотри код, если интересно.
← →
uw (2003-06-01 00:18) [26]Посмотри этот код. С точки зрения памяти и какой-либо инициализации object и record идентичны. Но у object есть объектно-ориентированные преимущества.
type
TObj = object
a: Integer;
b: Integer;
procedure DoAnything;
end;
procedure TObj.DoAnything;
begin
// I don"t want to do anything
end;
procedure TForm1.FormCreate(Sender: TObject);
var
o: array[1..100] of TObj;
begin
o[23].a := $1234;
o[23].b := $2345; // Перед этим оператором o[23].b <> 0
o[23].DoAnything;
end;
← →
vuk (2003-06-01 01:30) [27]to Alex Konshin:
>Беда только в том, что у NewInstance нет параметров и нет
>легального способа сказать ему где и как ее выделять.
Ну... Насколько я понял разработчиков RTL, они исходили из предположения, что для класса память выделяется только каким-то одними способом...
>Короче, смотри код, если интересно.
Угу. Я скачал библиотеку. Будет время - покопаюсь.
← →
Alex Konshin (2003-06-01 03:43) [28]
> >Беда только в том, что у NewInstance нет параметров и нет
>
> >легального способа сказать ему где и как ее выделять.
> Ну... Насколько я понял разработчиков RTL, они исходили
> из предположения, что для класса память выделяется только
> каким-то одними способом...
Способ-то один, но вот нельзя его параметризировать.
Страницы: 1 вся ветка
Текущий архив: 2003.06.16;
Скачать: CL | DM;
Память: 0.52 MB
Время: 0.005 c