15 ноября 2017 г. в 11:38
Добро пожаловать в эру Quantum - Как Firefox снова стал быстрый и в чём он станет ещё быстрее

Представляю на внимание перевод статьи из блога Lin Clark на hacks.mozilla.org. Низкая скорость работы, медленный интерфейс – главная причина, по которой люди бежали с Firefox. Сейчас всё иначе, Firefox не только стал быстрее, но и принёс в процесс рендеринга множество инноваций, главная из которых – параллельный рендеринг. Вчера вышел релиз Firefox 57 с огромным количеством улучшений, очень рекомендую его попробовать.

Люди заметили, что Firefox снова быстрый.

За последние семь месяцев мы стремительно заменили основные части движка, представив Rust и части Servo для Firefox. Кроме того, была начата грандиозная очистка кодовой базы для повышения производительности, как очевидной, так и не очевидной.

Мы называем этот проект Quantum, и первый общий выпуск возрожденного Firefox Quantum выходит завтра (прим. перев. 14 ноября).

Но это не означает, что наша работа выполнена. Это не означает, что сегодняшний Firefox предельно быстр и отзывчив, и так останется в будущем.

Так что, давайте посмотрим, в чем Firefox снова быстрый и в чем он будет ещё быстрее.

Укладка фундамента с крупнозернистым (coarse-grained) параллелизмом

Чтобы быть быстрее, нам нужно использовать преимущества железа, появившиеся за последние 10 лет.

Мы не первые, кто пытается это сделать. Chrome был быстрее и отзывчивее, чем Firefox, когда он был впервые представлен. Одна из причин заключается в том, что инженеры Chrome увидели, что происходят изменения в аппаратном обеспечении, и они начали лучше использовать это новое оборудование.

Стали популярны новые виды процессоров. Эти процессоры имели несколько ядер, что означало, что они могли выполнять несколько задач независимо друг от друга, но в то же время — параллельно.

Хотя, это может быть и сложно. С параллелизмом можно допустить коварные ошибки, которые трудно увидеть и трудно отладить. Например, если двум ядрам необходимо добавить 1 к одной и той же области в памяти, одно из ядер, скорее всего, перепишет другое, если вы не будете проявлять особой осторожности.

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

В браузере довольно легко найти эти крупные зёрна. У каждой вкладки есть своя, отдельная часть работы. Есть также вещи кроме вкладок — например, браузер chrome — и они тоже могут обрабатываться отдельно.

Таким образом, страницы могут работать с собственной скоростью, при этом не блокируя друг друга. Если в фоновой вкладке имеется длительно исполняющийся скрипт, он не блокирует работу в активной вкладке.

Эти возможности и увидели инженеры Chrome. Мы тоже это увидели, но у нас был более суровый путь. Поскольку у нас была существующая кодовая база, нам нужно было спланировать, как разделить код, чтобы воспользоваться преимуществами нескольких ядер.

Это заняло некоторое время, но мы туда добрались. В рамках проекта Electrolysis мы, наконец, сделали доступной мультипроцессорность для всех пользователей. И Quantum, с другими проектами, делает наше использование крупнозернистого параллелизма ещё лучше.

Electrolysis

Electrolysis заложил основу для проекта Quantum. Он ввёл своего рода мультипроцессорную архитектуру, подобную той, которая была представлена в Chrome. Поскольку это было настолько большое изменение, мы ввели его медленно, тестируя его небольшими группами пользователей, начиная с 2016 года, прежде чем она стала доступной всем пользователям Firefox в середине 2017 года.

Quantum Compositor

Quantum Compositor перенёс композитор в свой собственный процесс. Самая большая победа здесь в том, что это сделало Firefox более стабильным. Наличие отдельного процесса означает, что при сбое графического драйвера не произойдёт падение всего Firefox. Но наличие этого отдельного процесса также делает Firefox более отзывчивым.

Quantum DOM

Даже при разделении содержимого окон между ядрами и наличии отдельного основного потока для каждого из них, по-прежнему остаётся много задач, которые должен выполнять основной поток. И некоторые из них важнее других. Например, реакция на нажатие клавиши важнее, чем выполнение сборки мусора. Quantum DOM даёт нам возможность определить приоритетность этих задач. Это делает Firefox более отзывчивым. Основная часть этой работы уже была завершена, но мы всё-таки планируем продолжить эту работу, введя упреждающее планирование (pre-emptive scheduling).

Наилучшее использование железа с мелкозернистым (fine-grained) параллелизмом

Однако, если мы смотрим в будущее, нам нужно использовать больше, чем крупнозернистый параллелизм.

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

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

Но с крупнозернистым параллелизмом вы не можете отделить работу от одного ядра другому. Здесь нет границ между работами.

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

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

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

Но мы знали, что браузер должен был сделать этот сдвиг, потому мы начали инвестировать в исследования. Мы создали язык, свободный от этих гонок – Rust. Затем мы создали браузерный движок – Servo – который полностью использовал это мелкозернистый параллелизм. Благодаря этому мы доказали, что этом может сработать, и что у вас будет меньше ошибок при движении быстрее.

Quantum CSS (aka Stylo)

Благодаря Stylo, работа по вычислению стилей CSS является полностью распараллеленой для всех ядерах процессора. Stylo использует метод, называемый кража задач (work stealing), для эффективного разделения работы между ядрами, так что они все остаются заняты. С помощью этого вы получаете линейное ускорение. Вы делите время, необходимое для вычисления таблицы стилей CSS, на столько ядер, сколько у вас есть.

Quantum Render (с поддержкой WebRender)

Другая часть аппаратного обеспечения, которая сильно распараллелена – это графический процессор. Он имеет сотни или тысячи ядер. Вы должны провести много планирования, чтобы убедиться, что эти ядра остаются такими же занятыми, как они могут. Это то, что делает WebRender.

WebRender выйдет в 2018 году и воспользуется преимуществами современных графических процессоров. Тем временем мы также атаковали эту проблему под другим углом. Проект Advanced Layers изменяет существующую систему уровней Firefox для поддержки пакетного рендеринга. Это дает нам немедленные выигрыши, оптимизируя в Firefox текущих моделей использования GPU.

???

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

Убедитесь, что мы продолжаем становиться быстрее и никогда не замедляемся

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

Поэтому мы создали ещё одну часть Quantum, чтобы исправить это… в основном, для нанесения удара по производительности браузера, которая найдёт эти проблемы и мобилизует команды для исправления их.

Quantum Flow

Команда Quantum Flow была этой ударной силой. Вместо того, чтобы сосредоточиться на общей производительности определённой подсистемы, они оптимизировали конкретные важные варианты использования – например, загружая ленту в социальной сети – и работали в разных группах, чтобы понять, почему это менее отзывчиво в Firefox, чем в других браузерах.

Quantum Flow принёс нам много больших побед производительности. По пути мы также разработали инструменты и процессы, облегчающие поиск и отслеживание этих типов проблем.

Так что же происходит с Quantum Flow сейчас?

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

Но есть одна проблема с этим подходом. Когда мы оптимизируем один вариант использования, мы можем деоптимизировать другой. Чтобы предотвратить это, мы добавляем много инструментов отслеживания, включая усовершенствования автоматизации CI, выполняющие тесты производительности, телеметрию для отслеживания, что пользователи испытывают, и управления регрессией внутри ошибок. С этим, мы ожидаем, что Firefox Quantum будет продолжать улучшаться.

Завтра всё только начинается

Завтра большой день для нас в Mozilla. В течение прошлого года мы активно работали над тем, чтобы сделать Firefox быстрым. Но это только начало.

В течение следующего года мы будем постоянно улучшать производительность. Мы с нетерпением ждем возможности поделиться ими с вами!

Попробуйте релиз Firefox Quantum или выпуск Developer Edition, чтобы быть уверенным, что вы получаете последние обновления по мере их появления.