Совет 23. Рассмотрите Возможность Замены Ассоциативных Контейнеров Отсортированными Векторами.

«Даже если гарантированное время логарифмического поиска вас устраивает, стандартные ассоциативные контейнеры не всегда являются лучшим выбором.

Как ни странно, стандартные ассоциативные контейнеры часто уступают по производительности банальному векторному контейнеру» — К.

Мейерс «Эффективное использование STL».

Многих может заинтересовать практическая сторона этого совета: насколько на самом деле может быть быстрее отсортированный вектор, чем ассоциативные контейнеры.

Меня тоже заинтересовал этот вопрос и я решил провести небольшой тест и нарисовать пару графиков, чтобы все встало на свои места.

Для начала немного теории (тем, кто знает, что такое вектор и карта, читать не нужно).

Карта в STL — это ассоциативный контейнер для хранения пар ключ-значение.

Данные в нем хранятся в отсортированном виде, хотя стандарт C++ не определяет реализацию; чаще всего карта реализуется в виде красно-черного дерева, в котором каждый элемент хранит указатели на двух дочерних элементов.

Вектор в STL — это просто контейнер элементов, который гарантирует, что хранящиеся в нем данные не будут фрагментированы.

Эффективный поиск в нем можно организовать посредством сортировки и дальнейшего бинарного поиска.

Как и в первом случае, сложность поиска равна O(ln(n)).

Разница в скорости будет варьироваться за счет лучшего кэширования во втором случае (данные располагаются локально и для хранения требуется меньше памяти).

Для сравнения скорости вставки и поиска я написал тестовая программа , который производит два типа измерений — запись случайных значений (random(3)) в контейнеры при измерении времени (с помощью gettimeofday) и поиск случайных значений в контейнере за определенное время (10 с).

Таким образом измеряется время вставки данных в контейнер и количество поисков в контейнере за интервал времени.

Инструменты: Аппаратное обеспечение: Двухпроцессорный (Intel Xeon E5420) сервер без файла подкачки.

Программное обеспечение: сервер Ubuntu с ядром 2.6.28, gcc 4.3.3. Компилируем проект с ключами: -O3 -felide-constructors -fno-Exceptions -fno-rtti -funroll-loops -ffast-math -fomit-frame-pointer -march=core2 Каждый тест запускался несколько раз (N=10) и фиксировались минимальное, максимальное и среднее значения какого-либо параметра.

При проведении тестов разница полученных значений была минимизирована (снижение нагрузки на сервер, установка cpu affinity).

Данные, полученные при вставке элементов в контейнеры

Совет 23. Рассмотрите возможность замены ассоциативных контейнеров отсортированными векторами.
</p><p>



Совет 23. Рассмотрите возможность замены ассоциативных контейнеров отсортированными векторами.
</p><p>

На первом графике показана зависимость времени вставки и сортировки контейнеров в зависимости от количества элементов.

Обе шкалы логарифмические, поэтому для наглядности построена еще одна кривая, показывающая сумму времени вставки и сортировки для вектора — она показана пунктиром.

Горизонтальные черные линии показывают ошибку для каждого эксперимента – максимальное и минимальное значения.

Как видите, для 1 миллиона записей время вставки и сортировки вектора примерно в 10 раз меньше (0,11 с), чем для карты (1,1 с).

Данные, полученные при поиске элементов в контейнерах

Совет 23. Рассмотрите возможность замены ассоциативных контейнеров отсортированными векторами.
</p><p>



Совет 23. Рассмотрите возможность замены ассоциативных контейнеров отсортированными векторами.
</p><p>

На втором графике показана зависимость количества поисков, выполняемых за единицу времени (10 секунд), от количества элементов в контейнере.

Вы можете видеть, что скорость поиска в векторе выше, как и ожидалось выше, и на 1 миллион записей количество поисков в векторе примерно в 3,9 раза больше, чем в карте.

Из этих тестов видно, что производительность вектора может быть значительно (в 3,9 раза) выше, чем у карты, при этом заполнение вектора один раз и его сортировка также происходит быстрее (в 10 раз), чем у карты.

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

И как всегда нельзя забывать, что преждевременная оптимизация – это зло.

Теги: #C++ #STL #map #vector # Performance #C++

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.