Текущий архив: 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