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

Вниз

Статья "Написание оптимального кода под Delphi"   Найти похожие ветки 

 
AlexeyT ©   (2006-02-28 12:56) [0]

Внимание, в статье: http://delphimaster.ru/articles/optimization.html
есть ошибка:

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

На самом деле, такого нет, Delphi генерирует только один вызов функции (в данном случае, Length). Проверить это легко:

{$apptype console}

function Len(const s: string): integer;
begin
 Writeln("Len called");
 Result:= Length(s);
end;

var
 s: string;
 i: integer;
begin
 s:= "12345";
 for i:= 1 to Len(s) do Write("*");
 Writeln;
end.


Программка выводит:
C:\Prog\Tests>for2.exe
Len called
*****

Включение-выключение оптимизации дела не меняет.
Автору статьи я несколько дней назад написал, что-то он не отвечает.


 
Сергей М. ©   (2006-02-28 13:46) [1]


> Автору статьи я несколько дней назад написал, что-то он
> не отвечает


Брось в него, автора, гранату.
Со спецификацией Паскаля он вряд ли знаком.


 
Desdechado ©   (2006-02-28 13:58) [2]

Обсуждение статьи и ее ошибок происходит регулярно, где-то раз в 1.5 месяца. Но исправлять авторский текст может только сам автор.


 
palva ©   (2006-02-28 23:46) [3]

Ну да. Мне от тоже не ответил. Обидно, что эта статья лежит на самом виду и все на нее натыкаются.


 
Lamer@fools.ua ©   (2006-02-28 23:48) [4]

>Но исправлять авторский текст может только сам автор.

Тем не менее, можно к авторскому тексту, сделать комментарий в виде сноски/ссылки и т. п.


 
Lamer@fools.ua ©   (2006-02-28 23:50) [5]

з.ы. После "тексту" запятая лишняя.


 
Defunct ©   (2006-03-01 02:03) [6]

>Но исправлять авторский текст может только сам автор.

Так может быть удалить эту статью пока автор не исправит.
Что думает Администрация форума по этому поводу?


 
Дмитрий Белькевич ©   (2006-03-01 04:34) [7]

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


 
novice_man ©   (2006-03-01 05:57) [8]

AlexeyT ©   (28.02.06 12:56)
{$apptype console}

function Len(const s: string): integer;
begin
Writeln("Len called");
Result:= Length(s);
end;

var
s: string;
i: integer;
begin
s:= "12345";
i := 1;
while i <= Len(s) do
  begin
    Write("*");
    inc(i);
  end;
Writeln;
end.


Странно, но в таком виде работает так как автор описал. При каждом цикле происходит вызов Len и если добавить такую строку s:= s + "1"; цикл становится бесконечным.


 
Джо ©   (2006-03-01 06:15) [9]

> [8] novice_man ©   (01.03.06 05:57)
> Странно, но в таком виде

Ничего странного. Этот "вид" кардинально отличается тем, что в нем используется while.


 
Джо ©   (2006-03-01 06:18) [10]

Почему бы не почитать спецификацию, вместо того, чтобы заниматься сомнительными эксперементами?

While statement
The while statement executes its constituent statement repeatedly, testing expression before each iteration

For statement
For purposes of controlling execution of the loop, the expressions initialValue and finalValue are evaluated only once, before the loop begins.
... The difference between this construction and the for...to statement is that the while loop re-evaluates finalValue before each iteration.

(c) Delphi Help.


 
07BB   (2006-03-01 06:30) [11]

Джо ©   (01.03.06 06:18) [10]
- В чем сила брат?
- в чтении мануалов
))

AlexeyT ©   (28.02.06 12:56)  
чем вам не нравиться идея избавиться от лишних вызовов функции(даже если пример на котором показывается пагубность данного действия не совсем подходит)?


 
AlexeyT ©   (2006-03-01 08:45) [12]


> чем вам не нравиться идея избавиться от лишних вызовов функции


Для For - _нет_ лишних вызовов функции. Наоборот, если я сделаю по его рекомендации, т.е. вынесу присваивание за тело цикла, у меня будет лишнее присваивание и лишняя переменная.


 
07BB   (2006-03-01 08:49) [13]

AlexeyT ©   (01.03.06 08:45) [12]
Если брать вариант когда у вас ~5 for экономии то же нет?


 
TUser ©   (2006-03-01 09:02) [14]

Тут вот подумалось. Есть ведь переводчики pascal -> C. Я знаю программу, где в модуле сказано, что код сделан с помощью p2c.

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

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


 
TUser ©   (2006-03-01 09:07) [15]

Собственно поясню. Программа очень широко используется уже лет 20. Когда-то ее написали на Паскале. Теперь существует в виде Си. Некоторые модули переведены явно автоматами. Циклы выглядят стандартно: for (i=0;i<...;i++). Есть подозрение, что некоторые автоматические трансляторы Си-Паскаль, не думают о том, что значение ... в теле цикла может меняться.

Исходников той программы под рукой, правда, нет, - так что все сказано по памяти.


 
MegaVolt ©   (2006-03-01 11:57) [16]

Кстати если я не ошибаюсь то вот такая конструкция:

for i=0 to L-1 do
 begin
    ...
 end;

если смотреть в исходниках, то регистр где хранится переменная окончания цикла, каждый цикл декрементируется на единицу, сравнивается с i, а затем инкрементируется.
Почему так сделано я не в курсе. Возможно добавление вычитание единицы у проца не занимает времени или ещё из каких то соображений.


 
Sapersky   (2006-03-01 12:56) [17]

Нет, обычно (не буду утвержать что всегда) делается вот такое:

i := L;
Dec(i);
If (i <= 0) then goto @Skip;
Inc(i);
@Cycle:
 <...>
 Dec(i);
 If (i = 0) then goto @Cycle;
@Skip:

В ассемблерном листинге, где вместо меток относительные джампы, увидеть это действительно сложно, сам недавно так лопухнулся.
Так что надо не просто смотреть, а трассировать.


 
Sapersky   (2006-03-01 12:59) [18]

Ошибка вышла: If (i <> 0) then goto @Cycle, jnz то есть.


 
Sapersky   (2006-03-01 13:20) [19]

Плохой из меня декомпилятор, невнимательный:
If (i < 0) then goto @Skip;
Хотя это не принципиально, вряд ли кто-то будет приведённый фрагмент запускать :)


 
Igorek ©   (2006-03-01 13:35) [20]

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


 
MBo ©   (2006-03-01 13:38) [21]

>Igorek ©   (01.03.06 13:35) [20]
Ты какой стиль имеешь в виду?


 
AlexeyT ©   (2006-03-01 14:11) [22]


> Igorek

Такой стиль, это вызов ф-ции в for? Нормальный стиль. Вся VCL написана в этом стиле, и это правильно. Выносить присваивание за тело цикла нужно только когда это значение используется где-то дальше (5 циклов for, как кто-то сказал).


 
Igorek ©   (2006-03-01 15:00) [23]


> Такой стиль, это вызов ф-ции в for?

Да. Неправильный это стиль.


 
isasa ©   (2006-03-01 15:12) [24]

Igorek ©   (01.03.06 13:35) [20]
А за конструкцию типа
 with TmyForm.Create(self) do begin
   ShowModal;
   Release;
 end;
сжигать на костре. :)


 
Crash Coredump ©   (2006-03-01 16:59) [25]


> Неправильный это стиль.


"Смотрите, смотрите! Вся рота шагает не в ногу, один мой сын в ногу"


 
Igorek ©   (2006-03-01 17:34) [26]

Посмеялись, теперь слушайте аргументы :)
1) такое поведение не есть типичным для разных языков; полезная привычка на Делфи пожет стать вредной на С++
2) несложно перед циклом написать int c = f() а потом for ... to c
3) после to подразумевается конечное значение переменной цикла, а не условие - иначе был бы while
4) кто не знает, может вставить функцию, на результат которой влияет цикл и получит неожиданное поведение

Достаточно?


 
Crash Coredump ©   (2006-03-01 17:39) [27]


> полезная привычка на Делфи пожет стать вредной на С++


Так в C++ и property нету...


 
isasa ©   (2006-03-01 17:50) [28]

Ну хорошо, поставим вопрос по другому, а так
for i:= Length(s) to 1 downto ...


 
isasa ©   (2006-03-01 17:52) [29]

Сорри
for i:= Length(s) downto 1  ...


 
Kerk ©   (2006-03-01 17:53) [30]

Igorek ©   (01.03.06 17:34) [26]
1) такое поведение не есть типичным для разных языков; полезная привычка на Делфи пожет стать вредной на С++


Это неважно.
Мне понравился подходящий к случаю аргумент Кайта - недословно: нужно пользоваться всеми возможностями инструмента, за него заплачено много.


 
Kerk ©   (2006-03-01 17:55) [31]

Чем меньше бессмысленых строк, тем выше читаемость.


 
ANB ©   (2006-03-01 17:58) [32]

Я обычно вытаскиваю Length за цикл. При отладке удобнее. Имхо.



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

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

Наверх




Память: 0.52 MB
Время: 0.039 c
15-1141470897
DenMaster
2006-03-04 14:14
2006.03.26
Можно ли такое сделать?


11-1123192059
Thaddy
2005-08-05 01:47
2006.03.26
Propose small change to _Tobj to the Dacha man ;)


15-1141036082
Loginov Dmitry
2006-02-27 13:28
2006.03.26
Про сайт...


4-1136416486
Piter
2006-01-05 02:14
2006.03.26
LoadLibrary, FreeLibrary


2-1142195886
kilop
2006-03-12 23:38
2006.03.26
Как приостановить процесс работы проги?





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