Логические операции и быстродействие в FileMaker

Попробуйте вычислить в уме:

(5-5)*(17/(345-34,458)-242299)

Полагаю, вы затратили на вычисление не больше двух секунд, верно? А все потому, что вы знаете арифметическое правило: при умножении на ноль любого числа получится ноль. Зная это, вы попросту не стали вычислять второй множитель, а сразу назвали результат.

Если вы еще не знали, я раскрою вам небольшой секрет: вычислительное ядро файлмейкера (calculation engine) тоже знает это арифметическое правило. И его, и другие правила он применяет, чтобы сократить время вычислений.

Какая нам от этого секрета польза, спросите вы? У нас что, регулярно в файлмейкере применяется умножение на ноль?

Арифметики действительно в filemaker не много. Зато filemaker регулярно производит логические вычисления, которыми вы его нагружаете. Логические операции очень просты, но имеют свои хитрости. Если знать их и применять в построении выражений, то можно значительно повысить производительность приложений.

Файлмейкер выполняет четыре логические операции и использует четыре логических оператора: AND, OR, XOR и NOT.

Вот примеры логических вычислений:

If(Order::date = Get(CurrentDate) AND Order::total > 0; 1)

If(Order::date = Get(CurrentDate) OR Order::total > 0; 1)

В логических выражения все, что находится слева и справа от логического оператора, рассматривается приложением как элемент особого типа: булево. Эти элементы, независимо от того, что они в себе содержат и как выглядят, всегда будут интерпретироваться как Истина или Ложь (1 и 0). В конечном счете логические операции — это операции с двумя числами: один и ноль. А результат вычисления —всегда тоже единица или ноль.

Основные логические операции можно свести в таблицы, которые называют еще таблицами истинности


Таблицы истинности
С отрицанием вроде бы все понятно и просто. С исключающей дизъюнкцией (XOR) мы практически не работаем. А вот первые две операции нам определенно стоит изучить поподробнее. В них самая фишка зарыта.
Взглянем внимательно на две верхние таблицы.

Оператор AND в одной из них и оператор OR в другой вполне можно заменить на арифметический оператор, и «истинность» таблиц при этом не нарушится.

Действительно, AND можно заменить на знак умножения. А OR можно заменить на знак сложения. Смотрим


Не случайно конъюнкцию называют иначе «логическим умножением», а операцию OR называют «логическим сложением».

Все. Теперь вспоминаем арифметику младших классов, основные правила для умножения и для сложения. Для умножения ключевой элемент (множитель) — ноль. Сколько на ноль ни умножай, результат будет все равно ноль.

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

Что это означает? Элементарно: в половине случаев для того, чтобы вычислить весь результат, достаточно посчитать первый элемент. Смотрим на таблицы снова.


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

Это правило. Такое же, как в арифметике — умножение на ноль

Если при выполнении логического умножения (AND) окажется, что первый элемент (A) равен нулю, то и весь результат равен нулю.

Если при выполнении логического сложения (OR) окажется, что первый элемент (A) равен единице, то и весь результат равен единице.

Все, что нам нужно знать о поведении вычислительного модуля в FileMaker:

а) Он производит вычисление всегда слева направо. Первым вычисляется элемент А, вторым — элемент B.
б) при вычислении логических операций процессор учитывает описанные выше правила. Если для получения результата не требуется вычислять правый элемент B, то он и не будет вычисляться!

Теперь мы знаем, как повысить быстродействие приложение и убрать «тормоза». Все просто. Допустим, у вас есть выражение, в котором перед логической операцией вычисляются два значения.

If(Order::date = Get(CurrentDate) OR Order::total > 0; 1)

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

Но это еще не все.

Представим, что у нас есть два одинаково «тяжелых» вычисления (обозначим условно A и B). Будет ли важен порядок, в котором мы их прописываем в формулах файлмейкера? Ведь результат не меняется от этого (свойство переместительности):

A NOT B = B NOT A

A OR B = B OR A

A XOR B = B XOR A

На самом деле порядок повлияет на быстродействие и в этом случае, а в некоторых ситуациях это будет особенно заметно. Рассмотрим эти ситуации.

Допустим, мы используем знакомую нам формулу.

If(Order::date = Get(CurrentDate) OR Order::total > 0; 1)

Представим себе, что нам нужно это вычисление произвести n раз для N записей. Например, мы используем цикл или эта формула применяется в условном форматировании на странице типа «список». Допустим, у нас в цикле/в списке тысяча записей, и вычисление будет проводиться тысячу раз:

If(Order::date = Get(CurrentDate) OR Order::total > 0; 1)

If(Order::date = Get(CurrentDate) OR Order::total > 0; 1)

If(Order::date = Get(CurrentDate) OR Order::total > 0; 1)

If(Order::date = Get(CurrentDate) OR Order::total > 0; 1)

Понятно, что не во всех строчках Order::date = Get(CurrentDate) будет высчитываться одинаково. Скорее всего, большая часть массива (допустим, 99%) даст результат False, а вот несколько самых последних записей будет вычислено как True.

А Order::total > 0 для большей части записей будет вычислено как True.

Что получается? Поскольку у нас операция логическое сложение, а первый элемент в 99% записей дает результат ноль, то для большей части записей придется выполнить и вычисление второго элемента: Order::total > 0

А если в формуле поменять A и B местами, то результат совсем другой

If(Order::total > 0 OR Order::date = Get(CurrentDate); 1)

Теперь файлмейкер будет тысячу раз высчитывать Order::total > 0, но поскольку это практически всегда единица, то Order::date = Get(CurrentDate) вычислять практически не придется. То есть мы записали формулу таким образом, что файлмейкер будет делать на тысячу операций меньше. В ситуации, когда приходится обрабатывать большое количество записей, — это значительный выигрыш во времени.

Итак, второй принцип написания формул с логическими операциями. Если приходится вычислять одинаково сложные выражения, то определите вероятность, с которой выражение вычисляется как 1 или 0.

Если у вас оператор OR, то поставьте перед ним выражение, которое чаще всего или вероятнее всего выдаст результат 1.

Если в формуле оператор AND (логическое умножение), то поставьте перед ним выражение, которое чаще всего или вероятнее всего выдаст результат 0.

И будет вам быстродействие

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

Примечание 2. Это тоже было озвучено в обзорном докладе Аркадия Перла, но уместно напомнить еще раз.

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

Например,

Case(

case1; result1;

case2; result2;

case3; result3;

case4; result4;

case5; result5;

case6; result6;

case7; result7;

)

Файлмейкер не станет считать кейсы 4-7, если case3 возвращает ИСТИНА. Он возьмет результат этого кейса и сразу завершит вычисление. Поэтому разумно размещать кейсы упорядоченно от наиболее простых для вычисления (вначале) до самых сложных в конце.

Leave a Reply

Ваш e-mail не будет опубликован. Обязательные поля помечены *

84 − 79 =