Чем "нулевая безопасность звука" Dart отличается от нулевой безопасности Kotlin?

В этом официальном видео Dart говорится, что так называемая "безопасность нулевого звука" Dart лучше, чем дизайн нулевой безопасности Kotlin, поскольку он может оптимизировать код в зависимости от того, объявлена ​​ли переменная допускающей значение NULL, и других языков (я предполагаю, что это относится к языкам, включая Kotlin) должны выполнять проверки во время выполнения, чтобы гарантировать нулевую безопасность.

Итак, какая дополнительная оптимизация делает Dart?

Как он взаимодействует с устаревшими кодовыми базами, которые не поддерживают нулевую безопасность, обеспечивая при этом нулевую безопасность?

2 ответа

Звук дротика нулевая безопасность

Итак, какую дополнительную оптимизацию делает Dart?

Преимущество надежной защиты от нулей в Dart заключается в том, что компилятор может использовать необнуляемый тип , что позволяет исключить проверки на нуль . Следовательно, компилятор будет генерировать меньше инструкций (что приводит к уменьшению размера двоичных файлов и ускорению времени выполнения).

Пример

Возьмем следующую функцию:

      int getAge(Animal a) {
  return a.age;
}

Это инструкции, которые компилятор сгенерировал перед звуковой безопасностью null :

Как видите, в скомпилированном коде есть явные инструкции по проверке null.

А вот как выглядит та же функция, скомпилированная с надежной нулевой безопасностью :

Теперь эти дополнительные инструкции больше не нужны.

Обратите внимание, что фактические инструкции, сгенерированные, начиная с Dart 2.12, для примера функции следующие (были дальнейшие оптимизации):

Для справки см. Dart и преимущества производительности звуковых типов от Виджая Менона (ведущий инженер, Dart).

Совместимость с устаревшими кодовыми базами Dart

Как он взаимодействует с унаследованными кодовыми базами , которые не являются нулевыми (написанными до нулевой безопасности), обеспечивая при этом нулевую безопасность?

Это не так .

Что ж, это не вся правда. Если вы хотите использовать Дарт с любой кодовой базой, которая была написана до Dart 2.12 (и с ней до нулевой безопасности), вы не можете использовать надежную нулевую безопасность. Однако вы можете взаимодействовать с этими унаследованными кодовыми базами, передав флаг компилятора, который отключает надежную защиту от null. Это было бы (см. мой предыдущий ответ для более подробной информации).

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

Сравнение с Котлином

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

Имейте в виду, что Kotlin всегда допускает взаимодействие с Java , в которой нет концепции нулевой безопасности. Я полагаю, что это причина, по которой Kotlin никогда не сможет обеспечить надежную нулевую безопасность так же, как код Dart, который не взаимодействует с устаревшими кодовыми базами. Это до тех пор, пока код Kotlin скомпилирован для JVM с возможностью взаимодействия с Java.

NNBD

Если нас волнует не скомпилированный код, а только опыт разработчика, Kotlin и Dart одинаково справляются с нулевой безопасностью . То есть оба языка по умолчанию не обнуляемые (NNBD).

Это означает, что при написании кода в Dart 2.12+ или Kotlin все типы считаются необнуляемыми, если вы явно не пометите их как обнуляемые.
Единственный способ получить исключение нулевого указателя - это ошибка программиста на обоих языках, т.е. использование оператора bang в Dart и оператор двойного удара в Kotlin , то есть ненулевое утверждение разработчика.

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

Это также может произойти при взаимодействии с кодом Java при использовании Kotlin или при взаимодействии с устаревшим кодом при использовании Dart.

Есть еще несколько пограничных случаев, для справки см. Безопасность нулевых значений в Kotlin и Понимание безопасности нулевых значений в Dart .

Итак, какая дополнительная оптимизация делает Dart?

Самый простой вид оптимизации состоит в том, что при выполнении вычислений с числовыми типами компилятор может обрабатывать их (внутренне) как примитивные типы не ссылочных типов (неупакованные значения).

Это почему?

Поскольку они не могут быть нулевыми и, следовательно, нет необходимости использовать их как данные ссылочных типов (значения в рамке).

Это почему?

Поскольку null представлен в Dart как ссылка на константу null.
Если нет необходимости ссылаться на эту константу, почему бы не использовать типы значений вместо ссылочного типа? По крайней мере, в сгенерированном коде, который можно оптимизировать уже во время компиляции.

Все это благодаря так называемому «сильному режиму».
Сильный режим в сочетании с типами, не допускающими значения NULL, позволяет оптимизировать код уже на этапе компиляции, что очень важно для таких режимов, как AOT, которые не позволяют оптимизировать код во время выполнения, поскольку он находится в RE ( читать и выполнять) режим.

Как он взаимодействует с устаревшими кодовыми базами, которые не поддерживают нулевую безопасность, обеспечивая при этом нулевую безопасность?

Мне кажется, вам стоит задать это как отдельный вопрос.

Другие вопросы по тегам