Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Полезность оператора with 
:(
    Опции темы
Limonadni Joe
Дата 14.9.2003, 20:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 311
Регистрация: 1.11.2002
Где: Москва

Репутация: нет
Всего: 2



Может кто тестил: поднимает ли оператор with производительность при обращении к простым объектам (без индексирования, без разыменования и т.п.)? А может размер исходника уменьшается? Просто в справке по Visual Basic так и написано, что этот оператор ускоряет обращение к объектам, так как адрес объекта находится только олин раз. Правда, в справке по Dilphi об этом не написано.
PM MAIL ICQ YIM MSN   Вверх
p0s0l
Дата 14.9.2003, 20:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



Так и есть.
With компилится в загрузку в какой-нибудь из регистров (esi, edi) нужного адреса, а потом уже обращения происходят относительно этих регистров, т.е. адрес вычисляется всего 1 раз.



--------------------
С уважением, г-н Посол.
PM   Вверх
p0s0l
Дата 14.9.2003, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



Ну и соответственно на микроны повышается скорость (хотя если в большом цикле - то должно быть заметно) и уменьшается размер кода.



--------------------
С уважением, г-н Посол.
PM   Вверх
Akella
Дата 16.9.2003, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 36
Всего: 329



Не знаю как это сказывается на скорости работы программы, а вот на скорости разработки программы сказывается заметно
PM MAIL   Вверх
Vit
Дата 16.9.2003, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: 48
Всего: 207



Хм... Сравнил 2 кода:

1)
Код

 var t:record
       a:integer;
       b:integer;
     end;
     i:integer;
begin
 t.a:=0;
 t.b:=1;
 with t do
   for i:=0 to 1000000000 do
     begin
       a:=b+a;
     end;


2)
Код

 var t:record
       a:integer;
       b:integer;
     end;
     i:integer;
begin
 t.a:=0;
 t.b:=1;
 for i:=0 to 1000000000 do
     begin
       t.a:=t.b+t.a;
     end;


Разница во времени выполнения - 0.3% (быстрее с with) проверено на среднем арифметическом 10ти попыток...


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
Cashey
Дата 16.9.2003, 23:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бессмертный
****


Профиль
Группа: Завсегдатай
Сообщений: 3441
Регистрация: 13.11.2002
Где: в столице

Репутация: 2
Всего: 60



Цитата
Не знаю как это сказывается на скорости работы программы, а вот на скорости разработки программы сказывается заметно

Действительно, только не в пользу with, т.к. дельфя сама предлагает набор доступных свойств и методов объекта, который набираешь, это позволяет выиграть время, а главное, позволяет контролировать правильность набора названия (и наличия) его свойств, при использовании with эта ответственность ложится на плечи разработчика (кто из вас никогда не опечатывался smile.gif ). а компилятору я думаю пофигу, он все равно преобразует код в ассемблер, а в нем, насколько я знаю, оператора with нет.
Цитата
Так и есть.
With компилится в загрузку в какой-нибудь из регистров (esi, edi) нужного адреса, а потом уже обращения происходят относительно этих регистров, т.е. адрес вычисляется всего 1 раз.

А можешь привести простенький пример для иллюстрации?


--------------------
библия учит любить ближнего, а камасутра обучает как именно
PM Jabber   Вверх
Cashey
Дата 17.9.2003, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бессмертный
****


Профиль
Группа: Завсегдатай
Сообщений: 3441
Регистрация: 13.11.2002
Где: в столице

Репутация: 2
Всего: 60



Цитата
Хм... Сравнил 2 кода:

Я вот тоже решил сравнить
Код

procedure TForm1.Button1Click(Sender: TObject);
var
i :  Integer;
begin
Label1.Caption := timetostr(time());
with ProgressBar1 do
  for i:=0 to 1000000000 do begin
Position:=Round((i/1000000000)*100);
end;
Label2.Caption := timetostr(time());
Label3.Caption := timetostr(strtotime(Label2.Caption)-strtotime(Label1.Caption));
end;

Значит написал, откампилировал, перезагрузил комп (для чистоты эксперимента), запустил. Результат на C1300, 128Mb, WinME: 28:54.

И такой код
Код

procedure TForm1.Button1Click(Sender: TObject);
var
i :  Integer;
begin
Label1.Caption := timetostr(time());
//with ProgressBar1 do
  for i:=0 to 1000000000 do begin
ProgressBar1.Position:=Round((i/1000000000)*100);
end;
Label2.Caption := timetostr(time());
Label3.Caption := timetostr(strtotime(Label2.Caption)-strtotime(Label1.Caption));
end;

Значит написал, откампилировал, перезагрузил комп (для чистоты эксперимента), запустил. Результат на C1300, 128Mb, WinME: 29:03.

Разница 9 сек. или 2,65%. Вроде впечетляет, вот только часто ли вам приходилось крутить цикл миллиард раз? Интересно то, что первая разница в 1 сек. проявилась только в цикле
Код
for i:=0 to 10000000 do begin

Мое резюме такое: использовать оператор with или нет дело вкуса, на производительность это большого значения не имеет.




--------------------
библия учит любить ближнего, а камасутра обучает как именно
PM Jabber   Вверх
p0s0l
Дата 17.9.2003, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



Тот пример:
Код
var t:record
      a:integer;
      b:integer;
    end;
    i:integer;
begin
t.a:=0;
t.b:=1;
for i:=0 to 1000000000 do
    begin
      t.a:=t.b+t.a;
    end;

немного не то что я имел в виду...
Если например было бы типа такого:
Код

var
  t1 : array[0..1000] of record
     b1 : record c1, d1 : integer; end;
     e1 : byte;
   end;
  t2 : record
    b2 : array[0..1000] of record
      c2, d2 : byte; end;
    e2 : byte;
  end;

for i := 0 to 1000 do
 for j := 0 to 1000 do
    t1[i].b1.c1 := t.a1[i].b1.c1 + t2.b2[i].d2;

// вариант с with
for i := 0 to 1000 do
 with t1[i].b1, t2.b2[i] do
   for j := 0 to 1000 do
      c1 := c1 + d2;

Ну понял, что вычисление адреса переменной должно быть посложнее чем просто a.b...
Пример как это выглядит в откомпилированном виде покажу попозже...

Это сообщение отредактировал(а) p0s0l - 17.9.2003, 11:28


--------------------
С уважением, г-н Посол.
PM   Вверх
p0s0l
Дата 17.9.2003, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



Пример того, как работает with:
Код
type
 TRec1 = record
   a1 : array [0..1000, 0..1000] of record b1 : byte; end;
 end;

 TRec2 = record
   a2 : array [0..1000, 0..1000] of record b2 : byte; end;
 end;

var
 var1 : TRec1;
 var2 : TRec2;

procedure TForm1.Button4Click(Sender: TObject);
var
 i1, i2, j : integer;
 t1, t2 : integer;
begin
 i1 := Random(1000);
 i2 := Random(1000);
 t1 := GetTickCount;
 for j := 0 to 10000000 do
   Inc(var1.a1[i1, i2].b1, var2.a2[i1, i2].b2);
 t1 := GetTickCount - t1;

 i1 := Random(1000);
 i2 := Random(1000);
 t2 := GetTickCount;
 with var1.a1[i1, i2], var2.a2[i1, i2] do
   for j := 0 to 10000000 do
     Inc(b1, b2);
 t2 := GetTickCount - t2;

 Caption := IntToStr(t1) + ' / ' + IntToStr(t2);
end;


Тут разница 100мс против 60мс.

Вот как компилируется вариант без with (Delphi7):
Код
// for j := 0 to 10000000 do
mov eax, 10000000
// Inc(var1.a1[i1, i2].b1, var2.a2[i1, i2].b2)
imul edx, ebx, $3e9  // edx := i1*размер строки (i1=ebx, размер=$3e9)
add edx, offset var2 // edx := адрес строки в var2
mov dl, [edx+esi]    // dl := var2.a2[i1, i2].b2  (i2=esi)
imul ecx, ebx, $3e9  // ecx := i1*размер строки (i1=ebx, размер=$3e9)
add ecx, offset var1 // ecx := адрес строки в var1
add [ecx+esi], dl    // собственно, инкремент var1.a1[i1, i2].b1
// for (continue)
dec eax
jnz -$21

Адреса b1 и b2 вычисляются при каждом проходе цикла.

Вот как компилируется вариант с with:
Код
// with var1.a1[i1, i2], var2.a2[i1, i2] do
imul eax, ebx, $3e9  // eax := i1*размер строки  (i1=ebx, размер=$3e9)
lea edx, [eax+var1]  // edx := адрес строки в var1
add edx, esi         // edx := адрес b1
add eax, offset var2 // eax := адрес строки в var2
lea ecx, [eax+esi]   // ecx := адрес b2
// for j := 0 to 10000000 do
mov eax, 10000000
// Inc(b1, b2)
mov bl, [ecx]        // bl := b2
add [edx], bl        // b1 := b1 + b2
// for (continue)
dec eax
jnz -$07

Как видно, адреса b1 и b2 вычисляются только один раз до цикла и помещаются в регистры ecx и edx.

Если отключить оптимизацию, то по скорости получится 250 против 90...

Многое зависит от сложности вычислений и структуры записи/объекта - может получиться и так, что с with будет медленнее, чем без with, в частности, как я полагаю, если используется одновременно несколько with.
Поэтому такой совет - если нужна скорость в какой-то часто вызываемой функции (обычно связано с вычислениями и обработкой информации), то можно ПОПРОБОВАТЬ использовать with, или наоборот, убрать его (если уже стоит), т.к. с каждой версией Дельфи оптимизатор кода становится всё круче и круче, а with в некоторых случаях не дает ему поля для маневра...



--------------------
С уважением, г-н Посол.
PM   Вверх
Fantasist
Дата 18.9.2003, 06:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: нет
Всего: 41



Цитата
Адреса b1 и b2 вычисляются при каждом проходе цикла.


Вообще-то это странно. Оптимизатор вполне мог бы и заметить, что значение переменных в цикле не меняется, а значит можно вычислить их один раз и запихать в регистры и без всякого with. Правда возможно это уже будет в сторону того, что называют "агрессивная оптимизация".


--------------------
Волны гасят ветер...
PM MAIL   Вверх
p0s0l
Дата 18.9.2003, 06:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



Fantasist - да, оптимизатор в этом случае почему-то не оптимизировал это, хотя например циклы такого рода:
for i := 0 to n do a[i].param := i;
он оптимизирует нормально: перед циклом загружает в один из регистров адрес a[0], а потом уже в цикле увеличивает этот регистр на размер a[i], а в каком-нибудь другом регистре хранит обратный счетчик (от n к нулю) - т.е. если захочешь узнать значение i - простым способом никак не узнать, т.к. её уже нигде нет... Т.е. оптимизатор может узнать, на сколько меняется адрес переменной в цикле. А в том примере почему-то не додумался, что адрес вообще постоянный. Может дело в том, что массив двумерный ?
Ну это простой пример, но я иногда удивляюсь тому, до чего додумывается оптимизатор - если в следующий раз увижу какую-нибудь классную оптимизацию, то покажу её здесь (если не забуду)...

Это сообщение отредактировал(а) p0s0l - 18.9.2003, 06:36


--------------------
С уважением, г-н Посол.
PM   Вверх
Cashey
Дата 18.9.2003, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бессмертный
****


Профиль
Группа: Завсегдатай
Сообщений: 3441
Регистрация: 13.11.2002
Где: в столице

Репутация: 2
Всего: 60



По поводу оптимизаторов, я тут открыл топик http://forum.vingrad.ru/index.php?act=ST&f=21&t=12652, в котором развил тему продемонстрированного здесь эксперимента. Так вот в развитии темы: ОБРАТИТЕ ВНИМАНИЕ с оптимизатором Rain 1.0 скорость выполнеия цикла с with
Код
procedure TForm1.Button1Click(Sender: TObject);
var
i :  Integer;
begin
Label1.Caption := timetostr(time());
with ProgressBar1 do
 for i:=0 to 1000000000 do begin
Position:=Round((i/1000000000)*100);
end;
Label2.Caption := timetostr(time());
Label3.Caption := timetostr(strtotime(Label2.Caption)-strtotime(Label1.Caption));
end;


составило 26 мин. 50 сек., а кода без with

Код
procedure TForm1.Button1Click(Sender: TObject);
var
i :  Integer;
begin
Label1.Caption := timetostr(time());
//with ProgressBar1 do
 for i:=0 to 1000000000 do begin
ProgressBar1.Position:=Round((i/1000000000)*100);
end;
Label2.Caption := timetostr(time());
Label3.Caption := timetostr(strtotime(Label2.Caption)-strtotime(Label1.Caption));
end;

составило 26 мин. и 17 сек.!!!!!!!!
Вот вам и оптимизация.


--------------------
библия учит любить ближнего, а камасутра обучает как именно
PM Jabber   Вверх
Medved
Дата 18.9.2003, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 14
Всего: 154



Если взглянуть на инструкцию with с точки зрения хорошего стиля, то официально дядя Борман (т.е. Borland) рекомендуют следующее:
Инструкции with необходимо применять при достаточных на то основаниях и с большой осторожностью. Не следует злоупотреблять использованием иструкций with вообще и количеством применяемых в них объектов и записей в частности. Например, программные строки:
Код
with Record1, Record2 do

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

Хороший стиль - это накопленный опыт. Хороший стиль плохого не советует.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Fantasist
Дата 18.9.2003, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: нет
Всего: 41



Цитата
Инструкции with необходимо применять при достаточных на то основаниях и с большой осторожностью.


Вот, вот я сам всегда такого мнения придерживался. Читать код с with тяжелее, чем без него. Особенно когда идет вложенный with - это вообще капец.


Цитата
А в том примере почему-то не додумался, что адрес вообще постоянный. Может дело в том, что массив двумерный ?



Сама по себе двумерность массива роли не играет никакой - адрес то все равно вычисляется один. Но дело в том, что эта оптимизация потенцильно опасна для много поточных приложений. Если ты передал переменную в другой поток, а в этом цикле пытаешься мониторить ее значение, то оптимизатор тебя сильно обламает вычислив ее значение в самом начале.




--------------------
Волны гасят ветер...
PM MAIL   Вверх
p0s0l
Дата 19.9.2003, 01:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



Цитата
Сама по себе двумерность массива роли не играет никакой - адрес то все равно вычисляется один. Но дело в том, что эта оптимизация потенцильно опасна для много поточных приложений. Если ты передал переменную в другой поток, а в этом цикле пытаешься мониторить ее значение, то оптимизатор тебя сильно обламает вычислив ее значение в самом начале.

Дак это многопоточные проги ! Да и там я буду знать где можно использовать with, а где нельзя...
Цитата
Читать код с with тяжелее, чем без него.

Я конечно, не фанат with, но такое меня не устраивает:
TMyWebLoader(MyLoader).Job.Items.Delete(TMyWebLoader(MyLoader).Job.Items.Count-1);
по-моему легче прочитать это:
with TMyWebLoader(MyLoader).Job.Items do Delete(Count-1);
И бывают цепочки подлиннее...



--------------------
С уважением, г-н Посол.
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0801 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.