Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.02.05;
Скачать: CL | DM;

Вниз

Статья: "Оптимизация кода"   Найти похожие ветки 

 
Хинт ©   (2006-01-11 17:18) [0]

Увидел в новостях:
"Новая статья: Написание оптимального кода под Delphi"
Решил прочитать "свод правил, которые рекомендуется соблюдать при написании программ"
http://www.delphimaster.ru/articles/optimization.html

12. Выносите инвариантный код за тело цикла. Наиболее частая ошибка – for i:=1 to length(str) do... Дело в том, что при каждой итерации будет вызываться функция length, что пагубно скажется на производительности. Рекомендуется длину строки заранее присвоить переменной. Также не включайте в тело цикла код, заведомо не зависящий от изменения итерационной переменной.

А я вот всегда считал, что length(str) вычисляется только один раз...


 
Ega23 ©   (2006-01-11 17:25) [1]

k:=Length(Str);
for i:=1 to k do


 
Джо ©   (2006-01-11 17:27) [2]

> А я вот всегда считал, что length(str) вычисляется только
> один раз...

Правильно считал. Эту статью из-за этого примера уже года 2 ругают.


 
boriskb ©   (2006-01-11 17:28) [3]

Хинт ©   (11.01.06 17:18)
А я вот всегда считал, что length(str) вычисляется только один раз...


Это как ты считал?

То есть ты вызываешь функцию, а она.... что? Не работает? :))


 
Хинт ©   (2006-01-11 17:29) [4]


> В разделе "Статьи" обновление (31.01.05 14:20)


Могли бы уже и подправить за год. Получается их вообще никто не читает перед добавлением?


 
Хинт ©   (2006-01-11 17:31) [5]

2boriskb
Это значит, что в программах всегда писАл:
for i:=1 to length(str)
Так как были какие-то смутные воспоминания с лекций по Pascal"ю =)


 
Игорь Шевченко ©   (2006-01-11 17:32) [6]


> 12. Выносите инвариантный код за тело цикла. Наиболее частая
> ошибка – for i:=1 to length(str) do... Дело в том, что при
> каждой итерации будет вызываться функция length, что пагубно
> скажется на производительности. Рекомендуется длину строки
> заранее присвоить переменной


Автор соврал. Ни с включенной оптимизацией, ни с отключенной Length не вызывается при каждой итерации цикла.


 
Хинт ©   (2006-01-11 17:36) [7]

Так ладно бы автор один раз написал, так еще и в середине статьи:
Вынесение инвариантного кода за пределы цикла – не выносится. Наиболее распространенный недочет – условие цикла записывается как:


> for i:=0 to memo1.lines.count – 1 do...
>
>   Delphi будет при каждой итерации вызывать метод count,
>  вычитать из результата 1 и потом уже сверять. Настоятельно
> рекомендуется переписывать подобный код как
>
>
> lin := .lines.count – 1;
> for i:=0 to lin do...
>
>   Весь код VCL написан с нарушением этого правила. Очевидно,
>  что проще подобного рода оптимизацию встроить в компилятор,
>  нежели переписывать VCL :)


И еще:

>  Весьма печален и тот факт, что большинство кода VCL написано
> с точки зрения «красоты» кода, а не его оптимальности с
> точки зрения скорости. Например, не соблюдается правило
> 12


 
Anatoly Podgoretsky ©   (2006-01-11 17:37) [8]

boriskb ©   (11.01.06 17:28) [3]
Нет, она работает, но только когда вызывается.


 
Игорь Шевченко ©   (2006-01-11 17:39) [9]

Хинт ©   (11.01.06 17:36) [7]

Да пусть автор пишет некрасивый код в угоду скорости, кто ж ему запрещает ?


 
boriskb ©   (2006-01-11 17:40) [10]

Anatoly Podgoretsky ©   (11.01.06 17:37) [8]

Конечно :)
Осознал :)


 
iZEN_   (2006-01-11 19:38) [11]

for (int i = vector.size(); --i>=0;) {
...
}
Ж))
Зато быстро.


 
Marser ©   (2006-01-11 20:01) [12]

Тогда внимание вопрос - а кто проверяет статьи пред опубликованием? Архангельский и Флёнов? Или всё-таки кто-то из местных? Или прохалявили?


 
Piter ©   (2006-01-11 20:39) [13]

Ega23 ©   (11.01.06 17:25) [1]
k:=Length(Str);
for i:=1 to k do


а что ты этим хотел сказать?

Хинт ©   (11.01.06 17:36) [7]
>   Весь код VCL написан с нарушением этого правила


нда... хорошая статья :)

Marser ©   (11.01.06 20:01) [12]
Тогда внимание вопрос - а кто проверяет статьи пред опубликованием


а ты думаешь кто-то проверяет? Думаю, McSimm бегло просмотрит на наличие мата и типа того. Да и статьи на этом сайте нормальные авторы уже давно не публикуют.


 
Desdechado ©   (2006-01-11 20:48) [14]

автор статьи, видимо, пересел с Си
там границы цикла обсчитываются на каждой итерации
в паскале - только перед первой


 
DiamondShark ©   (2006-01-11 23:03) [15]


> for (int i = vector.size(); --i>=0;) {
> ...
> }
> Ж))
> Зато быстро.

Уродский язык...


 
DrPass ©   (2006-01-12 00:02) [16]


> пересел с Си
> там границы цикла обсчитываются на каждой итерации

Сишный и паскалевский циклы for - две большие разницы (с) неизвестный одессит. Сишный for вообще циклом с параметром не является, это просто наглядная запись цикла while.


 
wicked ©   (2006-01-12 00:09) [17]


> > for (int i = vector.size(); --i>=0;) {
> > ...
> > }
> > Ж))
> > Зато быстро.
>
> Уродский язык...

который из них?...... ;)


 
wicked ©   (2006-01-12 00:13) [18]


> Сишный и паскалевский циклы for - две большие разницы (с)
> неизвестный одессит. Сишный for вообще циклом с параметром
> не является, это просто наглядная запись цикла while.

скорей, продвинутая...


> for (int i = vector.size(); --i>=0;) {
> ...
> }
> Ж))
> Зато быстро.

зато с 1 ошибкой (грубой) и 1 "неэффективностью" (спорной, ибо поскипано тело цЫкла)...... :-P


 
McSimm ©   (2006-01-12 00:36) [19]

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

------
про C тут заговорили, вспомнилось:


#define begin {
#define end }
#define then
#define write printf

if (a > 10) then begin
 write(a);
end;


:)


 
Gero ©   (2006-01-12 00:55) [20]

> McSimm ©   (12.01.06 00:36)
> #define begin {
> #define end }
> #define then
> #define write printf
>
> if (a > 10) then begin
> write(a);

Классно :)


 
iZEN ©   (2006-01-12 10:03) [21]

wicked ©   (12.01.06 00:13) [18]

>> for (int i = vector.size(); --i>=0;) {
>> ...
>> }
>> Ж))
>> Зато быстро.

зато с 1 ошибкой (грубой) и 1 "неэффективностью" (спорной, ибо поскипано тело цЫкла)...... :-P

Какой ошибкой? Можно разъяснить?

Это, вообще-то, Java, а не "уродский язык" C++.
vector — экземпляр класса java.util.Vector.

Вот гарантированно рабочий код:

for (int i = vector.size(); --i >= 0;) {
  Object o = vector.elementAt(i);
  //...что-то делаем с o
}


 
wicked ©   (2006-01-12 10:37) [22]


> for (int i = vector.size(); --i >= 0;) {
>   Object o = vector.elementAt(i);
>   //...что-то делаем с o
> }

тогда вижу 1 неоднозначность - когда выполняется --i - до проверки условия?........

про ошибку напутал - с си++ код тоже будет валидным....
просто сачэм усложнять себе "внутренний дебугер" еще и вот такими конструкциями....

кстати, пользуясь случаем, позвольте выразить Вам неудовольствие по поводу унифицированного хранения обьектов в массиве.....
их же потом и кастить каждый раз нужно?.... в точкаНЕТ тож недалеко ушли - боксят/унбоксят значения....
вот.... ;)


 
iZEN ©   (2006-01-12 10:50) [23]

wicked ©   (12.01.06 10:37) [22].
Естественно, --i выполняется ДО проверки условия.
Счётчик работает на интервале от (size-1) до 0.
Усложнять это нужно затем, что метод size() везвращает значение каждый раз, когда к нему обращаются. В Java используются разные методики оптимизации кода, от простейшего интерпретатора и hotspot-стратегии JIT до оптимизации исполнения на стэке и, например, инлайнинг в будущем Mustang.
Так что если записать просто:

for (int i = 0; i < vector.size(); i++) {
...
}

мы получим тормоза за счёт обращения к методу size() на каждой итерации цикла. Ведь одна из границ цикла не определена, и размер vector может быть легко изменён в другой нити. Поэтому лучше делать так (защищённый код):

synchronized (vector) {
  for (int i = vector.size(); --i >= 0;) {
    Object o = vector.elementAt(i);
    //...что-то делаем с o
  }
}


 
iZEN ©   (2006-01-12 10:57) [24]

>wicked ©   (12.01.06 10:37) [22]
>кстати, пользуясь случаем, позвольте выразить Вам неудовольствие по поводу унифицированного хранения обьектов в массиве.....
>их же потом и кастить каждый раз нужно?.... в точкаНЕТ тож недалеко ушли - боксят/унбоксят значения....
>вот.... ;)

Есть разные контейнеры, которые позволяют хранить объекты по любой схеме: Vector, ArrayList, LinkedList и т.д.
В Java 5.0 есть генерики и шаблоны.
В Java 1.4 обходятся образцом проектирования Template Method при хранении родственных объектов в одном контейнере и/или используются фичи субсистемы Collection Framework.


 
wicked ©   (2006-01-12 11:03) [25]

> iZEN ©   (12.01.06 10:50) [23]
речь не о том.... код
> for (int i = vector.size(); --i >= 0;) {
>   Object o = vector.elementAt(i);
>   //...что-то делаем с o
> }

можно заменить на
> for (int i = vector.size() - 1; i >= 0; i--) {
>   Object o = vector.elementAt(i);
>   //...что-то делаем с o
> }
разницы никакой, а глаз (в т. ч. чужой, мой в этом случае) не спотыкается об непривычные конструкции....

если важен порядок обхода, никто не запрещает это написать так
> for (int i = 0, n = vector.size(); i < n; i++) {
>   Object o = vector.elementAt(i);
>   //...что-то делаем с o
> }
или уж, по "правильному"
> int n = vector.size();
> for (int i = 0; i < n; i++) {
>   Object o = vector.elementAt(i);
>   //...что-то делаем с o
> }
в обьектный код не глядел, но формально разницы никакой, а глаза опять таки "не цепляются".... плюс, если в java появились "итераторы", то код можно записать еще красивше... например, на си++ его можно записать так (принимая, что vector - это vector<object>)
> for (object * obj = vector.begin(); obj < vector.end(); obj++) {
>   //...что-то делаем с *obj
> }


 
iZEN ©   (2006-01-12 18:06) [26]

wicked ©   (12.01.06 11:03) [25]
> или уж, по "правильному"
> int n = vector.size();
> for (int i = 0; i < n; i++) {
>   Object o = vector.elementAt(i);
>   //...что-то делаем с o
> }

К сожалению, этот алгоритм не будет правильным в многопоточном окружении.
Когда объект vector доступен двум или большему числу нитей, то без предварительной блокировки объект vector может быть подвергнут ресайзу "вниз" (с удалением элементов) в одной из нитей в то же самое время как в другой нити будет идти итерация по элементам в цикле с верхней границей n, равной устаревшему значению. В итоге получим исключение времени исполнения java.lang.ArrayIndexOutOfBoundsException.
Нужно синхронизироваться для здоровой конкуренции за ресурс.


 
VictorT ©   (2006-01-12 18:11) [27]


>про C тут заговорили, вспомнилось:
>
>
>#define begin {
>#define end }
>#define then
>#define write printf
>
>if (a > 10) then begin
> write(a);
> end;

в printf кажись не может быть первый парметр быть числовым.


 
</code>   (2006-01-14 22:03) [28]

В статье написано правильно, вот пример:


procedure TForm1.Button1Click(Sender: TObject);
VAR I,a,t:INTEGER;
begin
 t:=GetTickCount;
 FOR I:=0 to round(exp(20)) do a:=a+a;
 t:=GetTickCount-t;
 Caption:=IntToStr(t);
 //t~=1900
end;

procedure TForm1.Button2Click(Sender: TObject);
VAR I,a,t:INTEGER;
begin
 a:=round(exp(20));

 t:=GetTickCount;
 FOR I:=0 to a do a:=a+a;
 t:=GetTickCount-t;
 Caption:=IntToStr(t);
  //t~=1265
end;


В первом случае t~=1900 ,во втором - t~=1265
Использовался D3.


 
Anatoly Podgoretsky ©   (2006-01-14 22:15) [29]

Ты хото понял что написал?


 
Джо ©   (2006-01-14 22:16) [30]

> [28]   (14.01.06 22:03)

Рекоммендую посмотреть ассемблерный код, дружище. Или, как минимум, составить корректные примеры. А то совсем недалеко от пресловутой лужи :)



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

Текущий архив: 2006.02.05;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.022 c
15-1137017293
Цукор5
2006-01-12 01:08
2006.02.05
Source


2-1137577282
Andrey235
2006-01-18 12:41
2006.02.05
Как програмно создать компоненту на форме?


15-1137267901
Ермак
2006-01-14 22:45
2006.02.05
Сайт по BlackBox


2-1137479131
VitalikS
2006-01-17 09:25
2006.02.05
Rave


15-1137058319
Volf_555
2006-01-12 12:31
2006.02.05
Проблема с автоматической установкой WinXP





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