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

Вниз

Классы, обьекты,...   Найти похожие ветки 

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.007 c
14-50464
Style
2003-05-28 08:13
2003.06.16
Тут мою музыку на студии обработали :)


1-50290
Voyager
2003-06-03 16:36
2003.06.16
Подскажите как усыпить процес


14-50470
Андрей
2003-05-29 23:00
2003.06.16
Программа на Delphi управляет второстипенными устройствами


14-50465
Дмитрий К.К.
2003-05-30 06:18
2003.06.16
Именинники 30 мая


1-50289
killer
2003-06-03 17:58
2003.06.16
Как программно создать новую кнопку в ToolBar?





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