Главная страница
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.55 MB
Время: 0.034 c
4-1132580395
Ботвин Дмитрий
2005-11-21 16:39
2006.02.05
Запись и воспроизведение действий пользователя


1-1136582035
Dunpeal
2006-01-07 00:13
2006.02.05
Картинки в RxRichEdit (не добавление)


15-1137085491
ArtemESC
2006-01-12 20:04
2006.02.05
Помогите решить задачу...


9-1124630358
Sphinx
2005-08-21 17:19
2006.02.05
Получить данные из VB Mesh-а


8-1125100654
WST
2005-08-27 03:57
2006.02.05
Работа с PNG