Основы офисного программирования и документы Word

         

Хронометраж


Давайте воспользуемся последним макросом, чтобы посмотреть на временной профиль выполнения тех или иных операций. Мне кажется, достаточно интересно, а иногда и крайне важно понять, на что уходит основное время при выполнении того или иного макроса. Я хотел понять также, как меняются временные затраты, если изменить реализацию макроса. Кроме того, нелишне напомнить Вам о необходимости следить за эффективностью выполнения программы.

Для того, чтобы построить временной профиль, я использую функцию Timer, добавляю специальные переменные для хранения времени выполнения отдельных участков процедуры и вставляю операторы, следящие за временем выполнения. Вот как выглядит теперь текст вышеприведенного макроса с надстройками, позволяющими проводить хронометраж операций:

Листинг 2.23.

(html, txt)

Приведу данные хронометража результатов испытания работы этой процедуры на одном из текстов.

Таблица 2.1. Временной профиль работы макроса - конструкции For Each и Select

N эксперимента123
TAll - Общее время работы2,1871,961,95
TForEach - Время работы внешнего цикла для конструкции For Each2,0781,861,86
TSelect - Время работы конструкции Select -Case1,010,801,08
TIndex1 - Время1 работы функции Asc00,0080,007
TIndex2 - Время2 работы функции Asc000
TSym1 - Время1 работы функции Mid0,00780,0310,04
TSym2 - Время2 работы функции Mid000

Поговорим о полученных результатах. Прежде всего, обратите внимание на разброс значений от эксперимента к эксперименту. Этот разброс всегда следует иметь в виду, хотя он, конечно, не искажает качественной картины построения временного профиля. Данные в таблице 1 приведены для случая, когда в макросе используется конструкция For Each для получения очередного символа коллекции Characters и конструкция Select - Case для разбора случаев и анализа того, каким является очередной символ. Вот некоторые выводы, которые можно сделать, анализируя полученные результаты:

  1. Основное время работы данной процедуры, примерно 2 секунды, затрачивается на организацию цикла (конструкцию For Each) и организацию разбора случаев (конструкцию Select - Case).
  2. На организацию цикла и разбор случаев тратится примерно равное время, чуть более секунды на организацию цикла и чуть менее секунды на организацию разбора случаев.
  3. Внутренние операторы конструкции Case, связанные с выполнением встроенных функций Asc и Mid, занимают пренебрежимо малое время в сравнение со временем, требуемым для организации конструкций цикла и разбора случаев, не более 5% от времени работы конструкции Select.


Заменим теперь конструкцию:

Select Case Sym Case "А" To "Я" <операторы1> Case "а" To "я" <операторы2> End Select на конструкцию: If Sym >= "А" And Sym <= "Я" Then <операторы1> ElseIf Sym >= "а" And Sym <= "я" Then <операторы1> End If

Листинг 2.24.

(html, txt)

Результаты вычислений в этом случае показаны в следующей таблице:

Таблица 2.2. Временной профиль работы макроса - конструкции For Each и If-Then-ElseN эксперимента123
TAll - Общее время работы2,062,021,98
TForEach - Время работы внешнего цикла для конструкции For Each1,971,931,89
TSelect - Время работы конструкции If-Then-Else0,970,960,89
TIndex1 - Время1 работы функции Asc0,0150,020,007
TIndex2 - Время2 работы функции Asc000
TSym1 - Время1 работы функции Mid0,0460,0510,02
TSym2 - Время2 работы функции Mid000
На данном примере трудно понять, какая конструкция работает эффективнее. Разброс значений соизмерим с погрешностью измерений. Я все-таки рекомендую применять конструкцию Select - Case в подобных ситуациях.

Приведем теперь более впечатляющие результаты, заменив конструкцию цикла:

Листинг 2.25.

(html, txt)

на обычный цикл:

For i = 1 To Selection.Characters.Count Sym1 = Selection.Characters(i)

Листинг 2.26.

(html, txt)

Вот как выглядят результаты временных замеров в этом случае:

Таблица 2.2. Временной профиль работы макроса - конструкции For I =1 To N и SelectN эксперимента123
TAll - Общее время работы106,53113,37115,84
TForEach - Время работы внешнего цикла для конструкции For Each106,44113,27115,74
TSelect - Время работы конструкции Select -Case0,1400,1480,187
TIndex1 - Время1 работы функции Asc0,020,030,015
TIndex2 - Время2 работы функции Asc000
TSym1 - Время1 работы функции Mid0,0780,0150,054
TSym2 - Время2 работы функции Mid000
Заметьте, вместо одной секунды на выполнение того же цикла теперь ушло около двух минут. Когда я впервые узнал, что при работе с коллекциями время, затрачиваемое на организацию старого, доброго и привычного цикла For I = 1 To N на два порядка больше времени работы цикла For Each, сказать, что я был поражен, слишком слабо. До сих пор не могу найти объяснения этому факту. Тем не менее этот факт имел место и в Office 97, такая же ситуация сохраняется и в Office 2000. Поэтому всегда в своих программах используйте, где можно цикл For Each - от этого существенно зависит эффективность выполнения ваших программ.


Содержание раздела