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

Вниз

Скорость работы с объектами в Delphi   Найти похожие ветки 

 
Strange man   (2007-07-17 20:55) [0]

Скажите пожалуйста, с чем быстрее работать - с "class-like" records или с классами? Насколько велика разница? Если учитывать, что записи тоже будут создаваться динамически, т. к. в основном они используются как Array of record.
Ещё встречный вопрос: с чем быстрее работать - с памятью в стэке или с памятью, выделенной динамически? Почему?
Поиск не помонает: http://www.google.com/search?hl=ru&q=%D1%87%D1%82%D0%BE+%D0%B1%D1%8B%D1%81%D1%82%D1%80%D0%B5%D0%B5+class+record&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&lr=


 
XProger ©   (2007-07-17 21:20) [1]

Strange man, разве сложно провести эксперимент?


 
Dib@zol ©   (2007-07-17 21:35) [2]


> "class-like" records или с классами?

По-моему со структурами, сиречь рэкордами. Тк. классы ешшо создать нада... А вообще было тут где-то такое обсуждение... Или не тут - не помню.


 
Сергей М. ©   (2007-07-18 10:28) [3]


> с чем быстрее работать - с "class-like" records или с классами?


Работа работе рознь.
Требуются уточнения..


> с чем быстрее работать - с памятью в стэке или с памятью,
>  выделенной динамически?


В общем случае индифферентно.


 
Strange man   (2007-07-18 12:40) [4]


> Работа работе рознь.
> Требуются уточнения..

Любые действия. Вызов методов, операции с полями

> В общем случае индифферентно.

А не в общем? :)


 
Ega23 ©   (2007-07-18 12:57) [5]

С объектами удобнее.


 
Сергей М. ©   (2007-07-18 12:58) [6]


> Вызов методов


Методы методам рознь.


> операции с полями


Операции операциям рознь.


> А не в общем?


А где упоминание о частности ?


 
Strange man   (2007-07-18 13:25) [7]


> Ega23 ©   (18.07.07 12:57) [5]
> С объектами удобнее.

С какими объектами? TObj = object?
Но вопрос об удобстве не стоит, вопрос стоит о скорости.


 
Сергей М. ©   (2007-07-18 13:27) [8]


> вопрос стоит о скорости


Ты что, атомы что ли расщепляешь там ?)

Или цацки-бирюльки компьютерные покоя не дают ?)


 
Ega23 ©   (2007-07-18 13:39) [9]


> Но вопрос об удобстве не стоит, вопрос стоит о скорости.


А что скорость? скорость есть приращение перемещения за промежуток времени. Первая производная, короче.
Что с ней не так?


 
Игорь Шевченко ©   (2007-07-18 13:47) [10]


> скорость есть приращение перемещения за промежуток времени


Это перемещение есть интеграл от скорости, не ври :)


 
Ega23 ©   (2007-07-18 14:00) [11]


> Это перемещение есть интеграл от скорости, не ври :)


плюс С


 
Sdubaruhnul   (2007-07-18 16:07) [12]

Есть такой компонент - VirtualTreeView. Он работает гораздо быстрее стандартного TreeView и многих других, потому что использует записи вместо классов, хотя это не единственная причина. Вот, в данном случае записи оказались быстрее.


 
Ega23 ©   (2007-07-18 16:10) [13]


> Есть такой компонент - VirtualTreeView.


есть такой.


> Он работает гораздо быстрее стандартного TreeView и многих
> других, потому что использует записи вместо классов


Гм... Записи чего? И вместо каких классов?


> хотя это не единственная причина.


Ты для начала загляни в реализацию TCustomTreeView, а потом говори.


> Вот, в данном случае записи оказались быстрее.


Быстрее чего(кого)?


 
Strange man   (2007-07-18 16:39) [14]


> Ты что, атомы что ли расщепляешь там ?)

Да, именно (классная шутка :|)

unit Unit2;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm2 = class(TForm)
   Button1: TButton;
   Label1: TLabel;
   procedure FormDestroy(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 end;

 TC = class
   a, b, c: Integer;
   procedure Proc;
 end;

 TR = packed record
   a, b, c: Integer;
   procedure Proc;
 end;

 procedure Proc;

var
 Form2: TForm2;
 cl1, cl2: TC;
 r1: TR;
 r2: Array of TR;
 a1, b1, c1: Integer;
 a2, b2, c2: ^Integer;

implementation

{$R *.dfm}

var
a3, b3, c3: Integer;

function GetTickCount: DWord;
var f, t: Int64;
begin
if QueryPerformanceCounter (t) then
begin
 QueryPerformanceFrequency (f);
 Result := Round (1000 * t / f);
end else Result := Windows.GetTickCount;
end;

procedure TC.Proc;
begin
a := 0;
end;

procedure TR.Proc;
begin
a := 0;
end;

procedure Proc;
begin
a3 := 0;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
i: Integer;
s: Dword;
a4, b4, c4: Integer;
begin
Label1.Caption := "";

s := GetTickCount;
for i := 0 to 1000000000 do proc;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "proc             " + IntToStr (s) + Chr($D);

s := GetTickCount;
for i := 0 to 1000000000 do r1.proc;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "record proc      " + IntToStr (s) + Chr($D);

s := GetTickCount;
for i := 0 to 1000000000 do r2[0].proc;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "dyn.array proc   " + IntToStr (s) + Chr($D);
s := GetTickCount;

for i := 0 to 1000000000 do cl1.proc;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "class proc       " + IntToStr (s) + Chr($D);

s := GetTickCount;
for i := 0 to 1000000000 do a1 := b1 + c1;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "int. var data    " + IntToStr (s) + Chr($D);

s := GetTickCount;
for i := 0 to 1000000000 do a2^ := b2^ + c2^;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "dynamic data     " + IntToStr (s) + Chr($D);

s := GetTickCount;
for i := 0 to 1000000000 do a3 := b3 + c3;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "imp. var data    " + IntToStr (s) + Chr($D);

 s := GetTickCount;
for i := 0 to 1000000000 do a4 := b4 + c4;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "local var data   " + IntToStr (s) + Chr($D);

s := GetTickCount;
for i := 0 to 1000000000 do with r1 do a := b + c;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "record data      " + IntToStr (s) + Chr($D);
   
s := GetTickCount;
for i := 0 to 1000000000 do with r2[0] do a := b + c;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "dyn.array data   " + IntToStr (s) + Chr($D);
     
s := GetTickCount;
for i := 0 to 1000000000 do with cl1 do a := b + c;
s := GetTickCount - s;
Label1.Caption := Label1.Caption + "class data       " + IntToStr (s) + Chr($D);

Beep;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
cl1 := TC.Create;
cl2 := TC.Create;
SetLength (r2, 1);
New(a2); New(b2); New(c2);
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
cl1.Free;
cl2.Free;
SetLength (r2, 0);
Dispose (a2); Dispose (b2); Dispose (c2);
end;

end.


В результате:

proc                2630        
record proc         2254
dyn.array proc      2254
class proc          2254
interface data      752
impl data           1060-1100
local data          375
dynamic data        1879
record data         752
dyn.array data      1377
class data          1879

Это "индифферентно"?


> Ega23 ©   (18.07.07 13:39) [9]
>
> > Но вопрос об удобстве не стоит, вопрос стоит о скорости.
>
> А что скорость? скорость есть приращение перемещения за
> промежуток времени. Первая производная, короче.
> Что с ней не так?

Да вы тут все прям остряки


 
Игорь Шевченко ©   (2007-07-18 16:46) [15]

Strange man   (18.07.07 16:39) [14]

Нафига ты такую бесполезную программу пишешь ?


 
Сергей М. ©   (2007-07-18 16:48) [16]

Твой "тупой" тест абсолютно ни о чем не говорит)

Бо ты ничерташеньки не шаришь в ключевых моментах)


 
Strange man   (2007-07-18 16:53) [17]


> Твой "тупой" тест абсолютно ни о чем не говорит)

И как сделать нормальный?


 
DevilDevil ©   (2007-07-18 16:54) [18]

Разница между record-ами и классами только в конструкторе/деструкторе.

Обращение к полям "по указателю" выполняется с одной скоростью. Обращение к свойству (read/write field) = обращению к полю.

Следующий вопрос.

К полям record-а в стеке обращение происходит в 2 раза быстрее. Но если пользоваться with, то все "потери" скорее всего соптимизируются до потери 1 такта.

P.S. мне кажется оптимизировать надо в других местах


 
Сергей М. ©   (2007-07-18 16:56) [19]


> как сделать нормальный?


Для начала изучить принцип действия конкретного оптимизирующего компимлятора.

Боюсь, тебе это не по силам, судя по амбициям)


 
Сергей М. ©   (2007-07-18 16:57) [20]


> К полям record-а в стеке обращение происходит в 2 раза быстрее


галиматья несусветная)


 
DevilDevil ©   (2007-07-18 16:58) [21]

если тебе так хочется это услышать, то "с классами работать не быстрее"


 
Сергей М. ©   (2007-07-18 16:58) [22]


> с классами работать не быстрее


Галиматья несусветная)


 
DevilDevil ©   (2007-07-18 17:00) [23]

var
 R : TRect;
begin
//...
 Result := R.Left; // 1 такт (1 операция)
end;

var
 R : PRect;  
//...
 Result := R.Left; // 2 такта (2 операции)


 
DevilDevil ©   (2007-07-18 17:03) [24]

function SomeProc(R : PRect) : integer;
begin
// ...

Result := R.Left; // 1 такт если eax не был запорчен
end;


 
DevilDevil ©   (2007-07-18 17:04) [25]

var
 R : TRect;

function SomeProc() : integer;
begin
// ...
 Result := R.Left; // 1 такт
end;


 
Strange man   (2007-07-18 17:05) [26]


> DevilDevil ©   (18.07.07 16:54) [18]
> Разница между record-ами и классами только в конструкторе/деструкторе.
>
>
> Обращение к полям "по указателю" выполняется с одной скоростью.
>  Обращение к свойству (read/write field) = обращению к полю.
>
>
> Следующий вопрос.
>
> К полям record-а в стеке обращение происходит в 2 раза быстрее.
>  Но если пользоваться with, то все "потери" скорее всего
> соптимизируются до потери 1 такта.

Спасибо.

> P.S. мне кажется оптимизировать надо в других местах

В каких?

> Сергей М. ©   (18.07.07 16:56) [19]

Можешь в 2х словах объяснить, почему мой тест тупой? Что я не учитываю?


 
Сергей М. ©   (2007-07-18 17:06) [27]


> Strange man   (18.07.07 17:05) [26]


С системой команд целевого ЦП ты, надеюсь, знаком ?


 
Strange man   (2007-07-18 17:10) [28]

Знаком, по крайней мере есть справочник


 
DevilDevil ©   (2007-07-18 17:10) [29]

> Сергей М. ©   (18.07.07 16:58) [22]
> с классами работать не быстрее
> Галиматья несусветная)


если вопрос в скорости обращения к полям... то "Какие ваши доказательства"(с) ?


 
Sdubaruhnul   (2007-07-18 17:11) [30]

>есть такой.

Спасибо за подтверждение.

>Гм... Записи чего? И вместо каких классов?

Если речь о TreeView, то можно было бы догадаться, что записи в качестве... там-дадам... УЗЛОВ.

>>>хотя это не единственная причина.

>Ты для начала загляни в реализацию TCustomTreeView, а потом говори.

Чё? Я так понимаю, что ты хочешь сказать, что единственная причина того, что VirtualTreeView работает быстрее, чем стандартный контрол - только в использовании записей в качестве узлов? Тем самым ты утверждаешь, что использование записей даёт такой существенный прирост в скорости?

>Быстрее чего(кого)?

Стандартного дерева, которое использует класс TTreeNode в качестве узлов.


 
Игорь Шевченко ©   (2007-07-18 17:12) [31]

DevilDevil ©   (18.07.07 17:00) [23]

Это было давно и неправда. На современных процессорах количество команд в единицу времени не выражается целыми числами с учетом конвейеров.


 
Сергей М. ©   (2007-07-18 17:13) [32]


> Знаком, по крайней мере есть справочник


Ну так и посмотри на код, генерируемый компайлером в том или ином случае !

В чем проблема-то ?


> DevilDevil ©   (18.07.07 17:10) [29]


см. выше)


 
Сергей М. ©   (2007-07-18 17:15) [33]

"блохоловы", блинн)


 
Сергей М. ©   (2007-07-18 17:15) [34]

"игролепщики")


 
Ega23 ©   (2007-07-18 17:17) [35]


> Чё? Я так понимаю, что ты хочешь сказать, что единственная
> причина того, что VirtualTreeView работает быстрее, чем
> стандартный контрол - только в использовании записей в качестве
> узлов? Тем самым ты утверждаешь, что использование записей
> даёт такой существенный прирост в скорости?


У тебя с адекватностью как? Я говорю, что яхта лучше чем первая казанка с подвесным мотором. А ты на основании этого делаешь вывод, что дизель - лучше. Потому что солярку использует.


 
Ega23 ©   (2007-07-18 17:19) [36]

Ещё раз рекомендую заглянуть в исходники TCustomTreeView и посмотреть, как этот монстр реализован.


 
DevilDevil ©   (2007-07-18 17:20) [37]

> Игорь Шевченко ©   (18.07.07 17:12) [31]

согласен. есть ряд вопросов, которые я недопонимаю. Почему до сих пор указывают такты, например. Какие-то по одному, ряд fpu-шных по 3 такта, деление - почти 30.

но стоит согласиться, что в среднем, 2 команды mov выполняются в 2 раза медленнее, чем 1. По данному поводу, надеюсь, характерных здесь придирок не будет.


 
Sdubaruhnul   (2007-07-18 17:49) [38]

>Ega23 ©   (18.07.07 17:19) [36]

Спасибо, но ничего полезного, а главное монструозного там нет. Ах да, пока я пишу эти строки, 500 000 узлов продолжают добавляться.

Теперь твоя очередь смотреть на VirtualTreeView. И про солярку больше не надо. Сначала смотри, что цитируешь, а потом отвечай.


 
Ega23 ©   (2007-07-18 18:03) [39]


> Спасибо, но ничего полезного, а главное монструозного там
> нет. Ах да, пока я пишу эти строки, 500 000 узлов продолжают
> добавляться.


BeginUpdate - EndUpdate поставил?
А ещё рекомендую посмотреть в сторону, например, CreateWnd - DestroyWnd


 
Ega23 ©   (2007-07-18 18:04) [40]

Я это всё к чему:
Неужели ты действительно считаешь, что VirtualTreeView работает быстрее ТОЛЬКО из-за того, что там рекорды используются в качестве описателя узла???


 
DevilDevil ©   (2007-07-18 18:40) [41]

> Strange man

Так что тебе надо оптимизировать?
Поподробнее, пожалуйста.


 
Sdubaruhnul   (2007-07-18 19:11) [42]

2 Ega23:

Нет, не только.

Но теперь скажу, к чему я всё это. Привожу текст из справки по VirtualTreeView:

"Aside many other problems one was especially annoying: How can adding some 5000-6000 nodes take a minute or so to finish? This question was the reason that I created the very first version of Virtual Treeview. What I actually did was to recall my studies where I learned my trade. Why, on earth, must everything be wrapped into an object? In Java and the like even simple data types like strings are objects. While this kind of abstraction provides some additional conveniences it costs quite a lot in terms of CPU power and memory, particularly if it comes to many instances of such simple type pretenders.

Basically, the idea of virtualizing the tree control and using records instead of classes were two ideas which are born nearly at the same time. It was quite clear from the very first moment that classes can never be as effective as a simple record structures (in terms of size, access speed and management). Sure, a TPersistent only needs 4 bytes more than a record (the pointer to the class" VMT), but these are still too many extra bytes if you consider that I have wrestled quite a while with myself about every byte in a tree node (and want the minimalism principle). Another point you should not underestimate is that classes as nodes would of course also mean to put node specific methods into this class too, which will be overridden at times (this is the main argument to use a class after all). This will require additional CPU cycles just to lookup access methods, to dereference etc. which in turn will cost extra time. Trees with only some 1000 nodes will never see a large difference but for big trees this is significant and Virtual Treeview has mainly been created to address high capacity tree views."


 
Strange man   (2007-07-18 19:26) [43]


> DevilDevil ©   (18.07.07 18:40) [41]
> > Strange man
>
> Так что тебе надо оптимизировать?
> Поподробнее, пожалуйста.

Я просто пытаюсь понять, насколько замедляет работу программы использование классов. Ты написал, что обращение к записи по указателю и обрашение к классу выполняются с одинаковой скоростью, но у меня в первом случае генерируется 7 команд, а во втором 9... Кстати, обращение к свойствам предков не медленнее? (у меня почему-то тоже 9 команд)


 
DevilDevil ©   (2007-07-19 08:24) [44]

Недопонял, что ты имеешь ввиду. Покажи код+асм. В 2х вариантах: со включённой опцией компилятора и выключенной.

Обращение к свойствам предков не медленнее. Обращение к виртуальным функциям так же одинаково по скорости.


 
Игорь Шевченко ©   (2007-07-19 10:40) [45]


> Another point you should not underestimate is that classes
> as nodes would of course also mean to put node specific
> methods into this class too, which will be overridden at
> times (this is the main argument to use a class after all).
>  This will require additional CPU cycles just to lookup
> access methods, to dereference etc. which in turn will cost
> extra time.


Странно звучит. То есть, для рекордов методы можно выносить отдельно, а для классов обязательно в них самих, да еще и виртуализировать ?
Это Коран такой или Талмуд ?
Любят люди себе проблемы придумывать на ровном месте.


 
DevilDevil ©   (2007-07-19 11:46) [46]

Звучит поерундовски


 
Strange man   (2007-07-19 12:25) [47]


> Недопонял, что ты имеешь ввиду. Покажи код+асм. В 2х вариантах:
>  со включённой опцией компилятора и выключенной.

Какая опция? Оптимизация? Если да, то код получается одинаковый:

with r1 do a := b + c;
 mov eax, [b]
 add eax, [c]
 mov [a], eax

with r2[0] do a := b + c;
 mov eax, [a]
 mov edx, [eax + $04]
 add edx, [eax + $08]
 mov eax, edx

with cl1 do a := b + c;
 mov eax, [xxx]  // Что здесь хранится?
 mov eax, [eax +  $08]
 mov edx, [xxx]
 add eax, [edx + $0c]
 mov edx, [xxx]
 mov [edx + $04], eax


С классом with почему-то не работает :(


> Обращение к свойствам предков не медленнее. Обращение к
> виртуальным функциям так же одинаково по скорости.

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


 
oxffff ©   (2007-07-19 12:27) [48]


> > Обращение к свойствам предков не медленнее. Обращение
> к
> > виртуальным функциям так же одинаково по скорости.


По сравнению с чем?


 
Игорь Шевченко ©   (2007-07-19 12:28) [49]


> Обращение к виртуальным функциям так же одинаково по скорости.


Одинаково с чем ?


 
oxffff ©   (2007-07-19 12:38) [50]

To Strange man  

Это для object

mov ebx,[eax+VTB Offset]
..
call [ebx+$MethodOffset]

Это для class

mov ebx,[eax]
..
call [ebx+$MethodOffset]

Если сравнить грубо, то одинаково.


 
Сергей М. ©   (2007-07-19 12:57) [51]


> Strange man   (19.07.07 12:25) [47]


Вместо занятия подобной ловлей блох лучше сосредоточиться на эффективном задействовании расширенных наборов инструкций ЦП - SIMD, MMX, XMM, 3DNow и иже с ними.


 
DevilDevil ©   (2007-07-19 13:17) [52]

> Strange man   (19.07.07 12:25) [47]

Если честно, не совсем понимаю смысл теста, лучше скажи, что в конечном итоге должно быть - мы подскажем слабые места.

> Что здесь хранится?

если там [ebp - что-то], значит сначала он "сохраняет" значение, находящееся в локальной переменной. Локальная переменная - указатель или объект класса.

если вообще какая то константа, то "сохраняет" значение, находящееся в глобальной переменной.

> oxffff ©   (19.07.07 12:27) [48]
> Игорь Шевченко ©   (19.07.07 12:28) [49]

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

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


На практике часто это правда. Зависит только от программста. Уменьшение в скорости если вызываешь, скажем, inherited.


 
DevilDevil ©   (2007-07-19 13:18) [53]

> Сергей М. ©   (19.07.07 12:57) [51]
> > Strange man   (19.07.07 12:25) [47]Вместо занятия подобной
> ловлей блох лучше сосредоточиться на эффективном задействовании
> расширенных наборов инструкций ЦП - SIMD, MMX, XMM, 3DNow
> и иже с ними.


А вот этого точно использовать не надо:
1) имхо
2) вряд ли это может пригодиться в твоей задачи
3) врядли осилишь реализацию


 
DevilDevil ©   (2007-07-19 13:21) [54]

SIMD - это и есть общее определение для всех расширенных наборов инструкций ЦП. XMM - это названия регистров. А вообще MMX, SSE(1, 2, 3), 3Dnow - этоже вроде SSE.

SIMD - имхо муть!


 
oxffff ©   (2007-07-19 13:25) [55]


> Обращение к виртуальным методам предков по сравнению с обращением
> к методам потомков


Вызов обычного метода или виртуального через inherited линкуется напрямую.

Вызов виртуального метода  происходит через VTB, т.е + 2 fetch из памяти.
Один VTB, второй entry point.

Так что разница между этими вызовами есть.


 
oxffff ©   (2007-07-19 13:30) [56]


> SIMD - это и есть общее определение для всех расширенных
> наборов инструкций ЦП.


AMD64 тоже расширение набора. Но не SIMD.

The AMD64 architecture is a simple yet powerful 64-bit, backward-compatible extension of the industry-standard (legacy) x86 architecture.


 
Сергей М. ©   (2007-07-19 13:40) [57]


> вряд ли это может пригодиться в твоей задачи


Это не моя задача)


> врядли осилишь реализацию


Да что ты ?!)


> SIMD - имхо муть


Угу. Просто так придуман, не для вас, игролепов-блохоловов)


 
Strange man   (2007-07-19 13:43) [58]


> Если честно, не совсем понимаю смысл теста, лучше скажи,
>  что в конечном итоге должно быть - мы подскажем слабые
> места.

Объясни пожалуйста, как заставить компилятор генерировать

mov eax, [xxx + $04]
mov edx, [eax + $04]
add edx, [eax + $08]
mov eax, edx


или хотя бы

mov eax, [xxx]
mov edx, [eax + $08]
add edx, [eax + $0c]
mov [eax + $04], edx


вместо

mov eax, [xxx]  
mov eax, [eax +  $08]
mov edx, [xxx]
add eax, [edx + $0c]
mov edx, [xxx]
mov [edx + $04], eax


А то полулучается медленнее в полтора раза


> если там [ebp - что-то], значит сначала он "сохраняет" значение,
>  находящееся в локальной переменной. Локальная переменная
> - указатель или объект класса.
>
> если вообще какая то константа, то "сохраняет" значение,
>  находящееся в глобальной переменной.

Нет, там просто смещение.

У меня класс
TC = class
  a, b, c: Integer;
  procedure Proc;
end;


А xxx - это [a - 4]. Что это может быть?


 
DevilDevil ©   (2007-07-19 14:03) [59]

> Сергей М. ©   (19.07.07 13:40) [57]

Я цитировал тебя, а обращался к нему.

> Strange man   (19.07.07 13:43) [58]

mov eax, [xxx]  // занести в eax значение переменной
mov eax, [eax +  $08] // buf := eax.SomeField;
mov edx, [xxx] // занести в edx значение переменной2
add eax, [edx + $0c] // buf := buf + edx.SomeField2;
mov edx, [xxx] // занести в edx значение переменной3
mov [edx + $04], eax // edx.SomeField3 := buf;


врядли можно заставить компилятор это с оптимизировать. Хотя, всё может быть, поставь оптимизацию в опциях компилятора, может Delphi "сотворит чудо"

1) говори, какая у тебя итоговая задача
2) показывай код, который был переведён компилятором в такой асм-код


 
Strange man   (2007-07-19 14:45) [60]


> DevilDevil ©   (19.07.07 14:03) [59]

Вот код с записью (r2: array of TR; setLength(r2, 1)):

with r2[0] do a := b + c;

mov eax, [a]               // Все расчёты ведём относительно первого поля "a"
mov edx, [eax + $04]   // edx = b
add edx, [eax + $08]    // edx = b + c
mov eax, edx              // eax = a = b + c


Здесь всё как надо. Смещение записи запоминается один раз. Тогда по логике и с классом должно быть также(cl: TC):

with cl do a := b + c;

mov eax, [xxx]             // Все расчёты ведём относительно смещения [xxx]
mov edx, [eax + $08]    // edx = b
add edx, [eax + $0c]    // edx = b + c
mov [eax + $04], edx   // a = edx = b + c


НО на практике получается так

with cl do a := b + c;

mov eax, [xxx]                    // 1
mov eax, [eax +  $08]          // eax = b
mov edx, [xxx]                    // 2
add eax, [edx + $0c]           // eax = b + c
mov edx, [xxx]                   // 3
mov [edx + $04], eax          // a = eax = b + c


Почему смещение [xxx] запоминается 3 раза? Это особенность использования классов? Это первый вопрос.

А второй вопрос: почему расчёты ведутся относительно [xxx], а не относительно первого поля "a"? Что находится в [xxx]?


 
Сергей М. ©   (2007-07-19 15:09) [61]


> with cl do a := b + c;


Мало ли в Бразилии "Педро" ?)

Строчка

with MyClass.Create(..) do a := b + c;

дает блохоловам ровно три asm-инструкции)


 
oxffff ©   (2007-07-19 15:10) [62]


> Что находится в [xxx]?


[xxx] Адрес объекта.
[ [xxx] ] адрес VTB
[[xxx]+$04] значение первого поля a


 
DevilDevil ©   (2007-07-19 15:18) [63]

ээээмм..

1) самое быстрое обращение будет к полям r1
2) r2 - переменная, хранящая указатель на r2[0]; переменная-динамический массив содержит указатель на первый элемент такого массива.
3) сделай r3 : ^TR. Проинициализируй и попробуй к нему так же обращаться. Скорее всего выйдет так же, как с классом.
4) попробуй выставить в опциях компилятора оптимизацию и сделай Build проекту. Мне кажется, инициализация одной и той же константой пройдёт.
5) указатель на рекорд = равен указателю на первый его элемент. так же как и с массивами. С классами иначе. Кроме заданных тобой данных, класс содержит некоторые свои данные (указатель на таблицу методов, например), надо посмотреть TObject.


 
Strange man   (2007-07-19 16:10) [64]


> Сергей М. ©   (19.07.07 15:09) [61]
> > with cl do a := b + c;
> Мало ли в Бразилии "Педро" ?)
> Строчка
> with MyClass.Create(..) do a := b + c;
> дает блохоловам ровно три asm-инструкции)

Но мне не надо вызывать create, класс уже создан, мне надо только изменить поле а.

> oxffff ©   (19.07.07 15:10) [62]
> [ [xxx] ] адрес VTB
>
> DevilDevil ©   (19.07.07 15:18) [63]
> Кроме заданных тобой данных, класс содержит некоторые свои
> данные

vtb - это виртуальная таблица чего-то? :) Где можно прочитать об этом?

> надо посмотреть TObject

В справке про vtb ничго не сказано

> сделай r3 : ^TR. Проинициализируй и попробуй к нему так
> же обращаться. Скорее всего выйдет так же, как с классом.

Если
var pr: ^tr;
pr:=@r1;
with pr^ do a:=b+c;

то код генерируется такой же, как для r2[0]. Или я не то сделал?

> выставить в опциях компилятора оптимизацию

Оптимизация у меня включена была с самого начала


 
DevilDevil ©   (2007-07-19 16:17) [65]

VMT - таблица виртуальных методов.

Пример. У каждого класса есть виртуальный метод Destroy. Если в своём классе ты напишешь виртуальный метод Destroy, то в таблице на месте метода Destroy будет содержаться указатель на твой метод Destroy, а не на метод твоего предка.

> то код генерируется такой же, как для r2[0]. Или я не то
> сделал?> выставить в опциях компилятора оптимизацию Оптимизация
> у меня включена была с самого начала


что то здесь не чисто...


 
DevilDevil ©   (2007-07-19 16:49) [66]

Я провёл тест. Гы!

Если написать pr.a := pr.b + pr.c;
тогда будет как с классом. :)

То есть with для классов не делает оптимизации, а для record-ов делает.

Потестите кто-нибудь на TurboDelphi, может лучше стало.


 
Strange man   (2007-07-19 17:01) [67]


> DevilDevil ©   (19.07.07 16:49) [66]
>
> Если написать pr.a := pr.b + pr.c;
> тогда будет как с классом. :)
>
> То есть with для классов не делает оптимизации, а для record-
> ов делает.

Так и есть :) Выходит у записей всё-таки преимущество перед классами :)
Большое спасибо!


 
DevilDevil ©   (2007-07-19 17:15) [68]

в "защиту" классов всё же скажу:

1) надеюсь, в TurboDelphi всё будет исправлено. А даже если не в Turbo, то в следующих версиях.

2) если с объектом предполагается проделать множество действий, то имеет смысл написать функцию, одним из параметров в которой будет этот класс. Или это будет метод этого же класса. В таком случае указатель на данные класса сразу будет храниться в регистре.

P.S.
> Большое спасибо!


Нет, нет, так просто ты не отделаешься!
Рассказывай, что у тебя за задача такая? Не расскажешь подробно - повешусь, тебя потом всю жизнь совесть будет мучать!


 
Strange man   (2007-07-19 17:48) [69]


> Нет, нет, так просто ты не отделаешься!
> Рассказывай, что у тебя за задача такая? Не расскажешь подробно
> - повешусь, тебя потом всю жизнь совесть будет мучать!

Да всё гораздо проще. Просто хочу написать игру, вот сначала и выясняю, стоит использовать классы, или нет, чтобы не делать грубых ошибок :) На первый взгляд вроде мелочь, а как оказалось, разница в скорость в полтора раза...


 
DevilDevil ©   (2007-07-19 18:07) [70]

Это не то место, которое надо оптимизировать!

Оптимизировать надо вывод графики.

- для 3D не выводить неотображаемые участки, оптимизация геометрии.
- стараться не использовать больших текстур (1024x1024) имхо уже много
- по возможности сжимать текстуры
- отработать механизм: хранить, какая в последний раз была активизирована текстура. и, если нужны, её размеры . Не активировать текстуру, которая была активирована последней.
- минимизировать "переключение" текущей текстуры.

Такая оптимизация даст прирост в разы.
Оптимизируя доступ к полям, ты не получишь и процента!

А что ты там хочешь record-ами делать.
Если удобнее классами, делай классами!

P.S. первый закон оптимизации: "оптимизировтаь надо слабые места!"


 
Strange man   (2007-07-19 18:12) [71]


> - по возможности сжимать текстуры
> - отработать механизм: хранить, какая в последний раз была
> активизирована текстура. и, если нужны, её размеры . Не
> активировать текстуру, которая была активирована последней.
>
> - минимизировать "переключение" текущей текстуры.
>
> Такая оптимизация даст прирост в разы.

Спасибо, учту


 
DevilDevil ©   (2007-07-19 18:38) [72]

не буду отвечать на вопросы в следующий раз, ну на фиг!

Я ему тут печатаю-печатаю, а он про рекорды рассказать не может...


 
oxffff ©   (2007-07-19 18:58) [73]


> Спасибо, учту


LOL.

Ты бы лучше дружок занялся нормальной оптимизацией BSP, portals, octree.

А лучше бы открыл бы SDK DIRECT 3D. И почитал.

General Performance Tips
Follow these general guidelines to increase the performance of your application.

Clear only when you must.
Minimize state changes and group the remaining state changes.
Use smaller textures, if you can do so.
Draw objects in your scene from front to back.
Use triangle strips instead of lists and fans. For optimal vertex cache performance, arrange strips to reuse triangle vertices sooner, rather than later.
Gracefully degrade special effects that require a disproportionate share of system resources.
Constantly test your application"s performance.
Minimize vertex buffer switches.
Use static vertex buffers where possible.
Use one large static vertex buffer per flexible vertex format (FVF) for static objects, rather than one per object.
If your application needs random access into the vertex buffer in accelerated graphics port (AGP) memory, choose a vertex format size that is a multiple of 32 bytes. Otherwise, select the smallest appropriate format.
Draw using indexed primitives. This can allow for more efficient vertex caching within hardware.
If the depth buffer format contains a stencil channel, always clear the depth and stencil channels at the same time.
Combine the shader instruction and the data output where possible. For example:

P.S.

Для классов.
У меня в любом случае 3 инструкции, что с with, что без
Что я не так делаю?


 
DevilDevil ©   (2007-07-19 19:07) [74]


> oxffff ©   (19.07.07 18:58) [73]

какая версия, больше 6 ?


 
oxffff ©   (2007-07-19 19:08) [75]

7


 
Strange man   (2007-07-19 22:05) [76]


> DevilDevil ©   (19.07.07 18:38) [72]

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



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.08.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.69 MB
Время: 0.044 c
15-1184255892
Petr V. Abramov
2007-07-12 19:58
2007.08.12
А почему в Маскве


2-1184610269
Knob
2007-07-16 22:24
2007.08.12
Как добавить в список


15-1184317254
TUser
2007-07-13 13:00
2007.08.12
Ошибка в 17й строке


15-1184193958
Германн
2007-07-12 02:45
2007.08.12
Отрицательные стороны совка


15-1184656246
Тульский
2007-07-17 11:10
2007.08.12
Open Office Calc и первичные ключи





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