Почему разница в скорости? - PullRequest
2 голосов
/ 22 апреля 2010

Рассмотрим этот код:

function Foo(ds as OtherDLL.BaseObj)
    dim lngRowIndex as long 
    dim lngColIndex as long

    for lngRowIndex = 1 to ubound(ds.Data, 2)
        for lngColIndex = 1 to ds.Columns.Count
            Debug.Print ds.Data(lngRowIndex, lngColIndex)
        next
    next
end function

ОК, немного контекста.Параметр ds имеет тип OtherDLL.BaseObj, который определен в указанной ActiveX DLL.ds.Data - это вариант двумерного массива (одно измерение содержит данные, другое - индекс столбца. ds.Columns - это коллекция столбцов в 'ds.Data`.

Предполагается, что вкак минимум 400 строк данных и 25 столбцов, этот код занимает около 15 секунд для запуска на моем компьютере. Это невероятно.

Однако, если я скопирую вариантный массив в локальную переменную, так:

function Foo(ds as OtherDLL.BaseObj)
    dim lngRowIndex as long 
    dim lngColIndex as long
    dim v as variant

    v = ds.Data
    for lngRowIndex = 1 to ubound(v, 2)
        for lngColIndex = 1 to ds.Columns.Count
            Debug.Print v(lngRowIndex, lngColIndex)
        next
    next
end function

все это обрабатывается практически в любое заметное время (в основном близкое к 0).

Почему?

1 Ответ

2 голосов
/ 22 апреля 2010

Скорее всего, ds.Data создает / копирует весь массив каждый раз, когда к нему обращаются (например, извлекает его из базы данных или чего-то еще), и это занимает значительное время.

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

Это распространенный и очень важный метод оптимизации: уберите из цикла любую ненужную работу, чтобы она выполнялась как можно меньше раз. Просто в вашем примере не «очевидно», что он выполняет много дополнительной работы при доступе к данным.

...