Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.55 MB
Время: 0.015 c
9-50199
Анат
2002-10-11 23:50
2003.06.16
Огонь


1-50367
NeshBriges
2003-06-04 02:07
2003.06.16
ExtractIcon


14-50491
b@nz@i
2003-05-26 16:09
2003.06.16
Наш ответ Их Fallout у (часть 2)


14-50506
Wonder
2003-05-30 12:50
2003.06.16
Чем у нас торгуют :)))


14-50478
Holy
2003-05-30 13:15
2003.06.16
Литература