Подтвердить что ты не робот

Является ли низкая производительность Excel VBA автоинституцией мифа?

Принятая мудрость заключается в том, что использование конструкции типа Dim dict As New Dictionary хуже, чем Dim dict As Dictionary / Set dict = New Dictionary.

Объяснение состоит в том, что предыдущий пример - авто-инстанцирование - исправляет экземпляр до первого использования переменной dict. И, таким образом, каждый раз dict ссылается, скомпилированный код должен сначала проверить, равен ли dict Nothing.

Но мне приходит в голову, что скомпилированный код делает это в любом случае. Вы получите ошибку при попытке использовать ссылку на объект Nothing.

Итак, в дань науке, я провел несколько тестов. И результаты показывают, что между двумя подходами нет разницы в производительности. (Запуск в Excel 2007)

Вызвать "создать словарь и добавить 2 элемента" 100 000 раз.

  • Явный: 16,891мс/Авто: 16,797мс (Авто 94мс быстрее)
  • Явный: 16,797мс/Авто: 16,781мс (Авто 16 мс быстрее)

Отмените порядок тестовых вызовов:

  • Авто: 16,766 мс/Явное: 16,812 мс (авто 46 мс быстрее)
  • Авто: 16,828мс/Явное: 16,813мс (Явное 15мс быстрее)

Вызвать "создать словарь и добавить 6 элементов" 100 000 раз.

  • Авто: 17,437мс/Явное: 17,407мс (Явное 30мс быстрее)
  • Авто: 17,343мс/Явное: 17,360мс (быстрее на 17 мс)

Создайте словарь и добавьте 100 000 элементов.

  • Авто: 391ms/Explicit: 391ms (Same)

Создать словарь и добавить 1 000 000 элементов.

  • Авто: 57,609мс/Явное: 58,172мс (Авто 563мс быстрее)
  • Явный: 57,343мс/Авто: 57,422 мс (Явное 79ms быстрее)

Я не вижу ничего, указывающего на то, что автоинверсификация - это плохое отношение к явному экземпляру. (Чтобы быть ясным, по другим причинам, я бы избегал авто-инстанцирования, но меня интересует только угол производительности здесь.)

Итак, это миф?

UPDATE

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

x.Add("Key", "Item")

в объекте с автоматическим инстанцированием эквивалентен следующему:

If x is Nothing then
    Set x = New Dictionary
End If
x.Add("Key", "Item")

что делает его похожим на "пугающие накладные расходы", если вы вызываете это тысячи раз. Но в явном экземпляре экземпляра это точно форма логики, сгенерированная в скомпилированной версии кода:

If x is Nothing Then
    Err.Raise "Object variable not set..."
End If
x.Add("Key", "Item")

Это не обязательно означает, что auto больше, поэтому я спрашиваю, есть ли в этом правда. Интересно, определил ли я еще один из многих непроверенных мифов о производительности.

4b9b3361

Ответ 1

Я знаю, что есть святой путь, если он в порядке или не тускнеет, как новый, но я никогда не слышал о том, что это говорит о низкой производительности. Короткий ответ "Не правда".. Да, это заставляет ваш код неуправляемые проверки, чтобы убедиться, что это не так, но вы не заметите разницы в скорости благодаря сегодняшним машинам. Это похоже на высказывание "за цикл более 10000 символов быстрее, чем 10001. Чтобы начать видеть какую-либо разницу, вам нужно зацикливать ваши тесты в более высоких выражениях, например, миллионы и десятки миллионов.

Говорят, что Dim, как New, неодобрительно, но не по соображениям производительности.

  • Вы теряете возможность управления при инициализации
  • Вы теряете возможность проверить, нет ли объекта Nothing.
  • Разница в скорости или нет, она засоряет ваш код неуправляемой проверкой.

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

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