﻿# Intel VTune Amplifier XE 2011 beta под строгим взглядом программиста

Решил посмотреть на новый Intel VTune Amplifier XE 2011 beta и написать статью о примере использования\. Правда, в процессе написания акцент частично сместился от использования Amplifier к его тестированию\. Но это тоже хорошо, надеюсь, разработчики в Intel учтут пожелания и внесут изменения в следующую версию инструмента\. И вообще буду критиковать и себя, и всех :\)\.

![0078_Intel_VTune_beta_ru/image1.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image1.png)

Начну немного издалека, иначе возникнут вопросы, зачем мне понадобился код, который мне пришлось оптимизировать\. В ходе разработки статического анализатора кода для Си\+\+ мне приходится сталкиваться с весьма экзотическими фрагментами программ\. Чего только программисты не придумывают\. И даже такие компиляторы, как Visual C\+\+ или Intel C\+\+ нет, нет, да и упадут на очередной "загогулине"\.

В нашем статическом анализаторе PVS\-Studio есть одно не очень хорошее место, связанное с определением типа объектов\. Есть, например, конструкция:

```cpp
typedef int A;
typedef A B;
B myValue;
```

и необходимо "вычислить" тип B, чтобы узнать, что это не что иное, как int\. С подобными примерами, конечно, никаких сложностей нет и все работает\. Однако бывают очень запутанные ситуации\. Приведу пример кода, демонстрирующего откуда начинают появляться разные сложности:

![0078_Intel_VTune_beta_ru/image2.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image2.png)

При попытке узнать тип переменной X мы посмотрим ее тип в namespace B и не найдем его там\. Тогда мы увидим, что надо посмотреть в namespace C\. И тоже там не найдем\. Теперь надо посмотреть и в namespace B\.\.\. Вечный цикл\. Конечно, это простой случай и с ним тоже никаких проблем нет\. Но добавьте сюда typedef, шаблоны, наследуемые классы\. Иногда получаются удивительно сложные вещи, причем не специально\. Особенно это проявляется в коде с шаблонами\.

К сожалению, инструмент PVS\-Studio иногда входил в вечный цикл на особенно "удачных конструкциях" и делал самоубийство через 5 минут, чтобы было возможно продолжить обработку других файлов\. Очень редкая ситуация, но неприятная\. Ошибки, конечно, правятся и правятся, но находятся все новые ситуации\. Причем не всегда есть возможность узнать, что же это за код такой у пользователя\. Было принято решение не полностью обрывать работу анализатора по таймеру, а отказаться от получения типа какого\-то объекта, если возникает зацикливание\. Лучше пропустить одну переменную, чем весь файл\.

Здесь проявляет очень интересный момент несовместимости  теории и практики\. Теоретически надо написать так, чтобы ошибок не было\. Даже пожурить нас можно\. Разработчики статического анализатора, писатели статей как писать без ошибок, а сами не могут сделать верный разбор типа переменных\. А вот получается, что не можем\. И не только мы\. Задачи, связанные с компиляцией Си\+\+ кода крайне сложные\. И приходится от рассуждений о высоком и прекрасном переходить к созданию заплаток на всякий случай\.

Был создан простой, но эффективный механизм остановки\. Если при получении типа объекта мы получаем указатель на закодированный тип, с которым уже работали до этого, то стоп\. Для начала был создан просто класс, содержащий множество указателей в std::set<const void\*\> \*m\_pGuardPointers\. Если в множестве уже есть указатель, то значит пора остановиться\.

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

```cpp
typedef long LONG;
LONG x;
```

Сразу был написан класс следующего вида \(приводится в сокращенном виде\):

```cpp
class CPointerDuplacateGuard
{
  static const size_t QuickMaxSize = 10;
  const void *m_ptrs[QuickMaxSize];
  size_t m_index;
  std::set<const void*> *m_pGuardPointers;
public:
  CPointerDuplacateGuard();
  CPointerDuplacateGuard(const CPointerDuplacateGuard *parent);
  ...
};
```

В начале, сохраняем и ищем указатели в обыкновенном массиве из 10 элементов, а уже затем создаем и начинаем использовать множество\. Стало значительно лучше, но все в несколько раз медленнее, чем без этого механизма\.

И вот здесь то я и решил, что пришло время посмотреть на Intel VTune Amplifier XE 2011 beta\. Очень хороший повод\. Здесь профилировщик как нельзя кстати\. Он поможет ответить на вопрос, связано падение производительности только с использованием std::set или замедление вносит само использование постоянных проверок указателя\. Если основное падение производительности связано с std::set, то нужно увеличивать значение QuickMaxSize\. Это отложит использование std::set на самый крайний случай\. Если замедляет сам алгоритм, то думать дальше\.

Сразу скажу, что как следует поработать с Intel VTune Amplifier XE 2011 beta у меня не хватило терпения\. Он вводит невообразимое торможение в работу\. Хотя у меня достаточно мощная система \(4 ядра, 8 Гбайт памяти\), если открыто окно Intel VTune Amplifier XE 2011 beta, то даже простое перемещение по коду делается с натугой и рывками\. Причем сам Intel VTune Amplifier XE 2011 ничего не делает\. Вернее процессор он нагружает, но не пишет, чем занимается\. Чтобы не быть голословным приведу демонстрационные скриншоты\.

Для большей наглядности, я прикрепил devenv\.exe к 4\-тому ядру\.

![0078_Intel_VTune_beta_ru/image3.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image3.png)

Итак, сейчас у меня открыт проект, ничего не происходит\. На рисунке видно, что загрузка четвертого ядра близка к нулю:

![0078_Intel_VTune_beta_ru/image5.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image5.png)

Теперь я просто запускаю Intel VTune Amplifier XE 2011\. Подчерку, что только запускаю\! Я не выполняю анализ проекта и вообще ничего не делаю\. Но четвертое ядро уже занято полностью:

![0078_Intel_VTune_beta_ru/image7.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image7.png)

Работать становится сразу как\-то некомфортно\. Среда начинает тормозить везде, где только можно\. Если закрыть окно Intel VTune Amplifier XE 2011 то торможение тут же пропадает и загрузка ядра снова становится близка к нулю\. Возможно, запущенный Intel VTune Amplifier XE 2011 делает какую\-то полезную работу\. Но какую непонятно\. Если делает \- то надо как минимум показать это\. У меня сложилось ощущение о какой\-то ошибке\.

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

![0078_Intel_VTune_beta_ru/image8.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image8.png)

Анализ выполнился без неожиданностей:

![0078_Intel_VTune_beta_ru/image9.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image9.png)

И я получил полезный результат:

![0078_Intel_VTune_beta_ru/image11.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image11.png)

Большинство времени тратится в std::\_Tree, в функциях выделения и освобождения памяти\. Программисту сразу станет понятно, что основное замедление связано именно с использованием std::set\.

Если запустить Amplifier в режиме Hotspot, то проблемное место станет гораздо очевиднее:

![0078_Intel_VTune_beta_ru/image12.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image12.png)

После этого запуска стало возможным просмотреть стек вызовов\. Правда, первый мой запуск в этом режиме закончился неудачей\. Меня предупреждали, что с включенной галочкой "Collect accurate CPU time" все будет медленнее\. Но получилось как\-то слишком медленно\. Когда я нажал на кнопку раскрытия стека для первой функции, то так и не дождался результата \(ждал 15 минут\)\.

Запуск уже без галочки показал нужную мне информацию\. Но и здесь не могу не добавить ложку дегтя\. Функционально инструмент замечателен, но интерфейс безобразен\. Все время что\-то разъезжается, не перерисовывается, что\-то смазывается\. Пользоваться неудобно и неприятно:

![0078_Intel_VTune_beta_ru/image14.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image14.png)

Впрочем, подводил не только внешний вид\. Иногда почему\-то перебрасывает на не тот участок кода, который необходимо\.

Однако нужный результат я все\-таки достиг\. Оказалось, что если установить значение массива в 64, то производительность возвращается приблизительно на прежний уровень\. Новая подсистема практически не вносит замедления в работу\. Исправление:

static const size\_t QuickMaxSize \= 64;



Это подтверждается и Amplifier\. Теперь на первый план вышли совсем другие функции, такие как strncmp:

![0078_Intel_VTune_beta_ru/image15.png](https://import.viva64.com/docx/blog/0078_Intel_VTune_beta_ru/image15.png)

## Выводы

Нет счастья в мире программ\. Кругом ошибки и недочеты\. У и нас в PVS\-Studio, и везде\. Это не значит, что с ними не надо бороться, но большой шаг хотя бы признать большую сложность программ и что ошибки есть\.

Пост получился несколько критичный по отношению к инструменту Intel VTune Amplifier\. Видимо это у меня как у разработчика наболело\. Предлагают попробовать очередную программу, которая улучшит мир, а как начинаешь с ней работать, то понимаешь, что больше потратили на маркетинг или красивые картинки, чем на контроль качества\. Ну что это за профайлер, который сам тормозит? Сапожник без сапог\. :\)

Надеюсь в Release это, или, по крайней мере, многое, будет поправлено\. Сам инструмент весьма мощен\. Но, к сожалению, пока рекомендовать его использовать не могу\. Конечно, подобное писать в блоге Intel как\-то не хорошо, зато честно\. Надеюсь, разработчики это оценят\.