В процессе разработки на платформе «1С:Предприятие» программисты часто сталкиваются с дилеммой: использовать конструкцию прямого неравенства <> или применять логическое отрицание к равенству НЕ ... =. На первый взгляд разница кажется несущественной, однако, если мы углубимся в механизмы работы платформы, интерпретацию байт-кода и вопросы поддержки программного продукта, ситуация становится более однозначной. В этой статье мы подробно разберем, какой вариант работает быстрее, почему это происходит и как писать код согласно стандартам индустрии.
Рассмотрим, что происходит «под капотом» платформы 1С при выполнении этих двух операций. Весь исходный код, который мы пишем в конфигураторе, перед исполнением транслируется в промежуточный байт-код (так называемый P-код). Этот код выполняется виртуальной машиной 1С.
Проанализируем ситуацию по шагам:
Х <> 0 интерпретатор генерирует одну элементарную инструкцию сравнения на неравенство. Система берет два операнда и сразу проверяет их на несовпадение.НЕ Х = 0 интерпретатор вынужден сгенерировать две последовательные инструкции. Сначала выполняется операция сравнения на равенство (=), результат которой (Булево) помещается в стек. Затем выполняется вторая операция — логическое отрицание (НЕ), которая инвертирует полученное значение.Вывод: С чисто технической точки зрения, вариант Х <> 0 требует меньше тактов виртуальной машины для исполнения. Хотя в масштабах одной операции эта разница измеряется наносекундами, в циклах с миллионами итераций она становится заметной.
Проанализируем результаты замеров, которые проводят опытные разработчики. В клиент-серверном варианте работы базы данных при выполнении циклов на 10 000 000 итераций конструкция <> показывает преимущество в скорости в среднем на 5–10% по сравнению с НЕ ... =.
Рассмотрим пример кода для самостоятельного тестирования скорости:
НачалоЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах();
Для Итерация = 1 По 10000000 Цикл
Если Х <> 0 Тогда
// Выполнение полезного действия
КонецЕсли;
КонецЦикла;
КонецЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах();
Сообщить("Время выполнения с оператором <> : " + (КонецЗамера - НачалоЗамера) + " мс");
НачалоЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах();
Для Итерация = 1 По 10000000 Цикл
Если НЕ Х = 0 Тогда
// Выполнение полезного действия
КонецЕсли;
КонецЦикла;
КонецЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах();
Сообщить("Время выполнения с оператором НЕ и = : " + (КонецЗамера - НачалоЗамера) + " мс");
Как правило, второй замер всегда оказывается медленнее. Это подтверждает теорию о двух операциях против одной.
Выясним, сохраняется ли эта разница при написании запросов. В языке запросов 1С выполнение кода передается на сторону СУБД (например, MS SQL Server или PostgreSQL). Здесь ситуация меняется.
Современные оптимизаторы запросов (Query Optimizer) достаточно интеллектуальны. Когда они встречают конструкцию NOT (X = 0), они автоматически преобразуют ее в X <> 0 еще на этапе построения плана выполнения. Для SQL-сервера эти выражения идентичны (идемпотентны). Поэтому в запросах разницы в скорости выполнения не будет.
Однако стоит помнить о работе с индексами. Использование неравенства (как <>, так и NOT =) чаще всего приводит к Index Scan (сканированию индекса), а не к Index Seek (поиску по индексу). Это означает, что если вам нужно отсечь небольшое количество данных, лучше стараться переписать условие через положительные сравнения или диапазоны.
Разберем ситуацию, когда X может принимать значения разных типов. Платформа 1С является системой с нестрогой типизацией в некоторых аспектах, но при сравнении она строго следует правилам приведения типов.
Если X изначально не является числом, система выполнит следующие действия:
Ложь, а на неравенство — Истина.НЕ Х = 0, если X — это строка "0", 1С вернет Ложь при сравнении с числом 0, и итоговое выражение превратится в НЕ Ложь, что даст Истина.Важно помнить, что НЕ Х = 0 может быть более «опасной» конструкцией в сложных выражениях из-за приоритета операций. Оператор = имеет более высокий приоритет, чем НЕ, но при беглом просмотре кода программист может ошибиться в логике инверсии.
Выясним, какой вариант рекомендует фирма «1С». В официальных стандартах разработки акцент делается на читаемости и простоте сопровождения. Программный код пишется в первую очередь для людей, а не для машин.
Почему Х <> 0 лучше для чтения:
<>, мозг сразу понимает условие.НЕ Х = 0 разработчик сначала должен осознать равенство, а затем выполнить в уме операцию отрицания. Это лишнее умственное действие, которое при больших объемах кода ведет к утомляемости и ошибкам.Рассмотрим пример сложного условия:
// Плохо читается
Если НЕ Объект.Статус = Перечисления.Статусы.Выполнен И НЕ Объект.ПометкаУдаления = Истина Тогда
...
КонецЕсли;
// Хорошо читается
Если Объект.Статус <> Перечисления.Статусы.Выполнен И Не Объект.ПометкаУдаления Тогда
...
КонецЕсли;
Проанализировав все аспекты — от низкоуровневых инструкций до стандартов чистого кода — мы можем сделать однозначные выводы:
<> выигрывает за счет выполнения одной инструкции вместо двух. В высоконагруженных алгоритмах и длинных циклах следует использовать именно его.<> является стандартом де-факто. Она более понятна коллегам по разработке и снижает риск возникновения логических ошибок.<>.Таким образом, всегда отдавайте предпочтение оператору неравенства <>. Использовать НЕ ... = стоит только в тех редких случаях, когда это обусловлено специфической логикой алгоритма, где инверсия результата сложной функции или выражения является более наглядной.