Знаете ли вы, что iOS поставляется с двигателем JavaScript, в комплекте в ОС? JavaScriptCore (JSC) – это тот же двигатель, который используется внутри Safari, завернутый в очень интересный API, который позволяет смешивать JavaScript и собственные значения вместе. Самое главное, когда он был введен в iOS 7, это также был единственный способ, которым Apple позволила вам выполнить загруженный код (за пределами веб -просмотра).
Они ослабили это ограничение в 2017 году разрешить другим переводчикам. Когда они это сделали, несколько выдающихся библиотек, ориентированных на JavaScript, переключили двигатели JS. Так почему же они бросили такой полностью изготовленный двигатель JS с OS-объединенным JS? Если вы используете JavaScript в своем приложении, не так ли? Недавно я сам пошел в эту кроличье дыру и подумал, что должен задокументировать этот процесс на случай, если это поможет следующей бедной душе.
Зачем мне даже запустить JavaScript в моем родном приложении? Чтобы попытаться предотвратить любое возмущение: вам не нужно! Никто не заставляет тебя! Но цикл выпуска App Store – это непостоянная, трудоемкая вещь, и иногда вы хотите иметь возможность действовать вне его. Вы часто можете сделать это с файлами конфигурации JSON, но иногда вам нужна более продвинутая логика, чем может предоставить JSON. Выступая за себя: я провел большую часть своей карьеры, работая в новостной индустрии, и нам часто нужно двигаться быстрее, чем процесс утверждения App Store позволит нам. Обычно это означает использование веб -просмотра Но я очень заинтересован в сценариях, где мы могли бы захотеть || выходить за рамки этого || Анкет
JavaScriptCore: быстро, за исключением случаев, когда это не так
JSC также связан с MacOS, и мне было любопытно, чтобы он сравнивал его, чтобы увидеть, как он сравнивается с V8, который Powers Node и Chrome. К моему удивлению, при беге V8 Web Tooling Clarkmark JavaScriptCore показал немного лучше, чем узел 14.
Узел 14 против результатов JavaScriptCore (Заказ V8 Web Tooling несколько лет, и на самом деле не так уж и не указывает на код реального мира, плюс он работает на мощном MacBook, а не на iPhone, так что ничего не читайте в необработанных числах, и доне t читал слишком много сравнения. Дело в том, что два двигателя «похожие») «Похоже»)
Но здесь есть важная морщинка: JavaScriptCore на MacOS (и внутри веб -браузеров на iOS) использует Jit повысить производительность. По соображениям безопасности, которые отключены, когда мы используем JSC в приложениях iOS. Запуск того же эталона с -usejit = false отрезвляет: замедление в 7,5x.
с JIT VS без результатов JIT
Итак, это раздражает. Мотивация к переключению двигателей? Возможно. Двигателям JS не разрешается использовать JIT, но V8 видит замедление 3,6x, когда JIT отключен.
Какого черта нет: узел против узла -Jitless
Но это еще не все: у V8 есть дополнительный трюк в рукаве, которого нет JavaScriptCore.
Байт -кодовое кэширование
Есть еще одна метрика двигателя JavaScript, которую мы еще не затронули: время запуска. В зависимости от того, что вы делаете со своим двигателем JS, это может иметь большое значение: если ваш пользовательский интерфейс контролируется JS, вам придется ждать запуска двигателя, прежде чем вы сможете показать что -либо пользователю.
Это не новая проблема для двигателей JS: время запуска также имеет большое значение в веб -браузерах. JavaScriptCore , V8 и Spidermonkey Все генерируют «байт -код» при анализе кода JavaScript. Это своего рода на полпути между источником текста и машинным кодом, который фактически выполняется, и его можно проанализировать намного быстрее, чем источник. Таким образом, двигатели кэшируют, что байт -код, а не просматривать строку каждый раз, увеличивая время запуска при возвратных посещениях.
К сожалению, внешний API JavaScriptCore не раскрывает эту функциональность. V8 API делает. NativeScript (структура для создания кроссплатформенного интерфейса в JavaScript) цитируется Это как одна из их важных причин перехода с JSC на V8. Facebook, потому что это Facebook, создал совершенно новый двигатель JavaScript под названием Hermes с Создание ByteCode на стадии компиляции приложения как ключевая цель. (Гермес представлен как библиотека Android, но девта с орлиными глазами, кажется, нашел доказательство того, что он также используется на iOS и .)
Чтобы проверить, насколько это может сделать разницу, я взял еще один двигатель JS, Quickjs для вращения (подробнее о этом двигателе позже). Специальный эталон веб -инструментов, который мы работали выше, является безумно большим 32 МБ .js файл. Для анализа исходного текста требуется QuickJS 2.9SECS, но сгенерировал байт -код от Этот текст занимает всего 150 мс. Я, конечно, надеюсь, что JavaScript, который вы хотите запустить в своем приложении, не 32 МБ, но достаточно сказать, что выгода от производительности примечательно.
Итак, мы все должны использовать V8, верно? Это быстрее по обоим пунктам!
Нет. Пожалуйста, не надо. Почему бы и нет? Ну, потому что библиотека имеет 7,5 МБ. Без возможности поделиться сторонним библиотеками между приложениями, что означает добавление значительной массы к вашему приложению. JavaScriptCore – это системная библиотека, поэтому она добавляет 0 МБ к любому приложению, которое его использует.
Часть, где я признаю, у меня нет хорошего ответа
Как это часто бывает, ответ на «Какой двигатель JS я должен использовать на iOS?» «это зависит». Я не думаю, что команда Nativesscript обязательно ошибается при выборе V8 с приложениями. Поскольку JavaScript управляет всем приложением, время запуска является для них огромным приоритетом. И, может быть, 7,5 МБ не так уж и важно, когда это то, что работает Все Анкет
Но я принял другое решение. Я создаю кроссплатформенную библиотеку JavaScript “Worker” под названием Esperanto Это завершает двигатель JS с некоторыми API -интерфейсом утилиты и жизненного цикла, которые направлены на то, чтобы сделать интеграцию JS в ваше существующее приложение безопасным и простым. Это все еще очень ранние дни (и это побочный проект, поэтому здесь требуется терпение) Но я хочу, чтобы ваш расчет затрат/выгоды при использовании Esperanto был простым. Если вы хотите использовать JavaScript только в одном крошечном углу вашего приложения, то требование 7,5 МБ дополнительной кодовой массы абсурдно. Так что я придерживаюсь JavaScriptCore. То, что есть более быстрые альтернативы, не означает, что JSC медленно. Если он работает достаточно хорошо для моих нужд, то отлично. Тем не менее, у меня есть возможный люк Escape.
Люк Escape: QuickJs
Esperanto работает также на Android, а у Android нет встроенной библиотеки JS (несмотря на то, что есть экземпляр V8 в пакете System WebView. Да ладно, Google!). И объединение JavaScriptCore на Android займет столько же места, сколько и V8 на iOS. Итак, для Android я обратился к двигателю под названием Quickjs Это удается упаковать весь двигатель (в комплекте с совместимостью с ES2020) в ~ 200 КБ кода. Не так хорошо, как 0 кб, но близко.
Несмотря на имя, это не объективно Быстро-я оценил его чуть менее половины производительности JSC без JIT-но с точки зрения удара для килобита, это довольно непревзойденное. И это позволяет вам кэшировать Bytecode. Что в конечном итоге станет более важным для Esperanto, времени запуска или общей производительности? Я не уверен. Но, учитывая, что я должен разработать версию QuickJS для Android в любом случае, я могу перевернуть переключатель и использовать QJS на iOS в будущем, если захочу. Или, может быть, я разработаю функцию, позволяющую вам выбрать, хотите ли вы запустить QuickJS, V8 или JSC в зависимости от того, как Ты используя библиотеку. Посмотрим.
Некоторые общие советы по использованию JS в ваших приложениях
Помимо выбора двигателя, я некоторое время экспериментировал в этой области и у меня есть несколько советов, которые могут быть полезны:
- Будьте осторожны с этими зависимостями Анкет Это относится к разработке JavaScript в целом, но NPM – это благословение и проклятие. Есть невероятное богатство библиотек у вас в руках. Но JavaScriptCore не браузер, и это не узел. Не разбивайте его с помощью мультимегабайтных зависимостей. Используйте Bundlephobia много.
- Получите местный, где вы можете Анкет JavaScriptCore’s Jsexport Функциональность – это действительно потрясающий способ беспрепятственного смешивания объективных классов C/Swift с вашим кодом JS. Используй это. Если вы знаете, что собираетесь выполнять особенно интенсивную работу (скажем, криптография), не устанавливайте библиотеку JS, чтобы сделать это. Напишите нативную функцию и выставьте ее в среде JS. Как бы вы ни могли, подумайте о своем JS как о клей между различными местными API, а не о своем собственном мире (Это принцип, который я применял в Эсперанто, где все кроссплатформенные API реализованы в Rust.)
Сноска: причины быть слегка оптимистичными
Команда JavaScriptCore четко признала это отсутствие доступности кэша ByteCode как слабость, потому что они Создал API Это позволит вам указать каталог для хранения кэшированного байт -кода, и вы можете Смотрите историю реализации кэша . Но JavaScriptCore с открытым исходным кодом – это не iOS JavaScriptCore: Apple выбирает, что принести и когда. Слишком поздно, чтобы сделать это, чтобы превратить это в iOS 14, так что пальцы скрещены, мы получим хороший сюрприз в 2021 году.
Оригинал: “https://dev.to/alastaircoote/to-jsc-or-not-to-jsc-running-javascript-on-ios-in-2020-44ba”