Мы с вами говорили, что код не может быть просто быстрым или медленным, он может быть достаточно или не недостаточно быстрым для задачи, которую он решает. Давайте рассмотрим пример: у нас есть программа, которая функцией main вызывает функцию generateBigVector и выводит на экран его размер. Функция generateBigVector устроена достаточно просто, она объявляет результирующий вектор, добавляет в него каким-то образом 28 тысяч строк и возвращает этот результирующий вектор. Давайте скомпилируем нашу программу, вот она компилируется и запустим ее, замерив время работы. Для этого я перейду в консоль, в который, я значит нахожусь в папке, где лежит мой проект, перехожу папку debug, и здесь есть файл coursera.exe, это собственно исполняемый файл программы, которую я только что скомпилировал, и давайте мы замерим время работы нашей программы. Мы запустили её и ждем. Программа выполнилась. Она вывела на экран 28 тысяч, это собственно размер нашего вектора, и мы видим, что программа работала 4.3. Ну кажется, что для программы, которая делает вектор из 28 тысяч строк, это как-то долго. Все таки современный компьютер уже достаточно мощный, чтобы решать эту задачу гораздо быстрее, и мы понимаем, что наша программа работает слишком медленно, и нам надо найти почему, что в нашей программе надо ускорить, чтобы она работала быстрее. Как мы это можем сделать? Ну мы можем воспользоваться интуицией. Например, можем рассуждать так։ функция generateBigVector формирует вектор из 28 тысяч строк и возвращает этот вектор через return, может возникнуть лишнее копирование и наверное из за него наша программа тормозит. Хорошо, давайте с этим как-то поборемся и напишем другую версию нашей функции, которая принимает вектор посылки и не будет выполнять лишнего копирования. Вот она принимает посылки, наполняет его, и давайте теперь запустим обновленную версию, generateBigVector result, вывести result size, компилируем, компилируется, отлично. Давайте снова запустим с замером времени и мы ожидаем, что сейчас у нас все будет летать. Запускаем программу, и что-то она опять долго работает. Даже давайте так, чтобы быть абсолютно уверенным, что мы нигде не ошиблись, пусть вторая версия нашей программы наполняет вектор 32 тысячами элементов, чтобы мы точно знали, что нужная функция вызывается, мы правильный файл запускаем. Вот, значит запустили, ждём, ждём, ждём-ждём. На экран вывелась 32 тысячи, значит мы правильную функцию запустили и она отработала 5,6 секунды. О чём нам это говорит? Это говорит о том, что интуиция нас подвела. Мы ожидали, что у нас там лишнее копирование и из за него наша программа работает медленно, но это оказалось не так. Я специально привел этот пример. Чтобы навести вас на второе правило оптимизации кода, который звучит очень просто, замеряйте! А если интуиция, которую мы используем для поиска узких мест в программе часто оказывается неверна и она субъективно, то измерение, они объективны и они позволяют нам действительно увидеть то место в программе, из за которого она работает медленно. Давайте мы последуем этому совету, давайте мы откроем снова нашу программу, уберем вторую версию функции generateBigVector вернем, здесь как было, компилируется, и давайте померим. Давайте померим, сколько работает вся наша программа и померим, сколько работает тело функции main. Мы уже с вами еще в белом поясе по С++ писали код измерения, вот давайте, когда изучали константные ссылки, давайте его повторим. Значит, мы запоминаем, когда наша программа начала работать и запоминаем момент окончания и выводим допустим stdr. Здесь магическая команда duration cast milliseconds finish-start. Так как у нас не влезает, мы сохраним эту разность в отдельную переменную и здесь count. Так мы замерим общее время работы нашей программы, и теперь давайте то же самое сделаем для, замерим, сколько работает у нас вот этот цикл. Мы видим здесь cycle, здесь мы видим total. Скомпилируем то, что у нас получилось, компилируется, и давайте запустим уже здесь внутри эклипса. Вот наша программа работает, и что мы видим? Она вывела в консоли с даты измерений, что общее время работы программ и время работы цикла по формированию вектора в миллисекундах совпадают, то есть большая часть времени уходит на работу вот в этом цикле. Наши измерения, мы померили время работы программы и наши измерения показали где у нас узкое место. Теперь мы можем посмотреть на этот цикл повнимательнее и пытаться понять, что же в нем не так. Ну если мы внимательно на нее посмотрим, то здесь выполняется вставка очередной стройки в начало вектора. В нашем втором курсе, в желтом поясе поясе по С++ мы обсуждали, что для удаления одного элемента из начала вектора приходится выполнять сдвиг всех элементов в начало, потому что вектор хранит все свои элементы последовательно, но при вставки происходит то же самое, у нас есть элементы вектора, мы выставляем в начало, значит все должны подвинуть вправо. Давайте мы поменяем этот код и будем вставлять элемент не в начало вектора, а в конец, с помощью метода push back. Компилируем нашу программу, у нас конечно тут сейчас, а, скобок не хватает, у нас нарушилась корректность работы этой функции, она в другом порядке стала вставлять элементы в вектор, но для наших целей это сейчас неважно. Итак, наша программа компилируется, давайте ее запустим, 6 миллисекунд. Мы видели, что она работала 4,5 миллисекунды, мы поменяли порядок вставки вектора и теперь она работает, наша программа работает 6 миллисекунд, то есть мы померили время работы отдельного куска программы, измерения показали нам, что он работает медленно и мы смогли его исправить и поверили, что мы действительно ускорились. Давайте подведем итоги, что мы узнали в этом видео? Прежде чем ускорять код, заметьте сколько он работает. Это относится еще к правилу про избегание преждевременной оптимизации. Если код работает достаточно быстро, то не надо тратить время на его оптимизацию и это время можно потратить на какую-то другую полезную работу. Если же измерения показали, что код работает медленно, то начинаете искать узкие места. Здесь мы вспоминаем принцип Парето о том, что есть 20% кода, которые влияют на нашу производительность. Можем сказать, что в нашем примере этими 20% был цикл функции generateBigVector, и чтобы ускорить нашу программу, мы ищем в ней узкие места. Как? Мы с вами пока посмотрели, увидели, что интуиция не помогает в поиске узких мест. Чтобы их найти, нужно измерить каждый блок программы и найти то место, в котором действительно ваша программа проводит больше всего времени.