Страница 27 из 39
Использование процедур и функций Всегда помните, что использование процедур и функций с ло- кальными переменными составляет основу структурного программиро- вания. Процедуры и функции являются строительными блоками прог- рамм на Турбо Паскале и составляют самое главное положительное качество данного языка. Вам следует знать несколько особенностей функций Турбо Паскаля, которые влияют на размер и скорость выпол- нения вашего кода. Во-первых, Турбо Паскаль является стеково-ориентированным языком: все локальные переменные и параметры используют стек для промежуточного запоминания. При вызове функции адрес возврата вызвавшей процедуры также помещается в стек. Это позволяет прог- рамме осуществить возврат в точку, из которой был вызов. Когда функция возвращает управление, данный адрес и все локальные пере- менные и параметры должны быть удалены из стека. Процесс заталки- вания данной информации в стек называется последовательностью вы- зова, а процесс выталкивания информации из стека - последовательностью возврата. Эти последовательности требуют оп- ределенного времени и иногда довольно большого. Чтобы понять, как вызов функции может замедлить вашу прог- рамму, рассмотрим два примера:
Версия 1 Версия 2 for x:=1 to 100 do for x:=1 to 100 t:=compute(x); t:=Abs(Sin(q)/100/3.1416);
function compute(q: integer): real; var t:real; begin compute:=Abs(Sin(q)/100/3.1416); end;
Хотя каждый цикл выполняет одну и ту же функцию, версия 2 гораздо быстрее, так как использование непосредственного кода устраняет задержки, связанные с последовательностями вызова и возврата. Для понимания того, сколько времени тратится, рассмот- рим следующий код на псевдоассемблере, который демонстрирует в теории последовательности вызова и возврата для функции compute:
; последовательность вызова move A, x ; поместить значение х в аккумулятор push A call compute ; инструкция вызова помещает адрес ; возврата в стек
; последовательность возврата ; значение возврата функции должно быть помещено в ; регистр - мы используем В move B, stack-1 ; доставить значение во временное t return ; возврат к вызвавшей процедуре ; вызвавшая процедура затем выполняет следующие действия
Использование функции compute внутри цикла ведет к тому, что последовательности вызова и возврата будут выполнены 100 раз. Ес- ли вы хотите написать быстрый код, то использование данной функ- ции внутри цикла - это не самый лучший подход.
Теперь вы можете подумать, что следует писать программы, ко- торые состоят из нескольких больших процедур и которые, следова- тельно, будут работать быстрее. В большинстве случаев, однако, небольшие различия во времени выполнения не важны, а вот потеря структуры будет ощутимой. Но это другая проблема. Замена вызовов подпрограмм, которые используются различными процедурами, на не- посредстевнные коды сделает вашу программу очень большой, так как один и тот же код будет дублироваться большее количество раз. Помните, что подпрограммы были выдуманы главным образом как средство повышения эффективности использования памяти. Положение таково, что убыстрение программы ведет к ее увеличению, а умень- шение программы ведет к ее замедлению. Использовать непосредс- твенный код вместо вызовов функций следует только тогда, когда скорость имеет абсолютный приоритет. В противном случае рекомен- дуется повсеместное применение процедур и функций.
|