Swift заменил C‑интерпретатор TrueType‑хинтинга: безопаснее и быстрее
Apple переписал интерпретатор хинтинга TrueType‑шрифтов с C на Swift, добившись 13 % прироста скорости и полной памяти‑безопасности.
Apple объявила о завершении миграции интерпретатора хинтинга TrueType‑шрифтов с C на Swift, запланированной к выпуску в осеннем обновлении 2025 года. Переписанный модуль стал полностью memory‑safe и в среднем работает на 13 % быстрее, чем его предшественник.
Почему потребовалась переписка?
TrueType‑шрифты используют байткод‑интерпретатор, который обрабатывает данные из потенциально недоверенных источников. Ошибки в управлении памятью в таком коде легко превращаются в уязвимости. Перенос на Swift позволил избавиться от классических проблем с указателями и переполнениями, сохранив при этом совместимость с существующим API.
Как обеспечивалась совместимость?
Была поставлена задача достичь пиксель‑идентичного рендеринга, как у C‑версии. Для этого разработчики создали два набора тестов: единичные тесты, покрывающие 99,7 % кода, и масштабный фузз‑тест, в котором из 10 млн PDF‑файлов отобрали 4 200, содержащие 25 572 шрифта и 27 млн глифов. Рендеринг всех глифов сравнивался с результатом референс‑интерпретатора.
Какие оптимизации дали прирост скорости?
- Отказ от копируемых типов – вместо классов использованы
~Copyablevalue‑типы, что устранило накладные расходы ARC и проверок эксклюзивности. - Span – структура из Swift 6.2, позволяющая работать с последовательностями без копирования, применена к массивам точек глифа.
- Проекции вместо копий – вместо копирования данных из C‑структуры в Swift был введён «projection type», дающий безопасный доступ к оригинальному блоку памяти.
- Ленивая обработка – заменены
map/filterна прямые циклы сcontinueи локальными переменными, что убрало лишние аллокации. - Оптимизированный стек – вместо возврата массива при
popиспользован continuation‑passing, позволяющий работать сSpan‑срезом без выделения памяти.
Что изменилось в кодовой базе?
Интерпретатор теперь реализован как @objc‑класс, вызываемый из Objective‑C++, но внутренние структуры объявлены как non‑copyable. Абстракции через протоколы и дженерики сохраняют читаемость без потери производительности, так как компилятор успешно их инлайнит.
Как проверяли производительность?
Сравнительные измерения проводились на уровне рендеринга PDF‑документов и на уровне микросекундных затрат CPU на один глиф. Диаграмма в оригинальном посте показывает, что для системных шрифтов Swift‑интерпретатор consistently быстрее, а для некоторых сторонних шрифтов C‑версия всё ещё выигрывает в отдельных случаях.
Что это значит для бизнеса?
Благодаря памяти‑безопасному Swift‑решению риск эксплойтов через шрифты снижается, а ускорение рендеринга уменьшает нагрузку на процессоры, особенно в облачных сервисах и на мобильных устройствах. Это приводит к более стабильной работе приложений и экономии ресурсов без необходимости менять клиентский код.