Основи продуктивності для розробників IBM Lotus Notes, Книги та статті, Різне, статті

В даному технічному описі розглядаються найважливіші та найбільш серйозні фактори, що впливають на продуктивність додатків IBM Lotus Notes і Domino. Воно призначене для розробників клієнтських додатків Notes і допоможе їм максимально підвищити продуктивність, ідентифікуючи проблемні області і пропонуючи рішення.

Передбачається, що ви вже знаєте, як створювати елементи дизайну Notes і як настроювати параметри форм, полів, уявлень, стовпців і т.д. Тут представлений матеріал для розробників будь-якої кваліфікації.


1. Введення


Прості програми в Lotus Notes розробляти легко, і якщо користувачам документів в додатку не дуже багато, у вас навряд чи виникнуть які-небудь проблеми з продуктивністю. Однак якщо додаток виявиться вдалим, в ньому може накопичитися багато даних і утворитися маса користувачів. Якщо додаток було спроектовано без урахування питань продуктивності, воно буде працювати повільно.


В даному технічному описі розглядаються основні чинники, що впливають на продуктивність додатків Notes / Domino, і пояснюється, що ви, як розробник, можете зробити для максимізації продуктивності. Це керівництво не є вичерпним, в ньому приділяється увага найбільш типовим і найбільш серйозних проблем проектування.


Мета даного опису – допомогти визначити проблемні області і вказати рішення проблем, головним чином для клієнтських додатків Notes. Web-додатки мають багато в чому аналогічні проблеми проектування, але у них є додаткові можливості та рішення для підвищення продуктивності, що розглядаються в “Додатку Group C”, документа IBM Redbooks “Обговорення питань продуктивності для додатків Domino“(EN) і в документі для бізнес-партнерів IBM”Проектування продуктивних додатків Notes / Domino” (EN).


2. Загальні принципи


На загальну продуктивність додатків найбільший вплив надають наступні чинники:



3. Продуктивність на рівні бази даних


Список параметрів, які можна використовувати для налаштування продуктивності бази даних, наведений у документі Domino Designer “Властивості, що підвищують продуктивність бази даних”. У більшості випадків ці параметри підвищують продуктивність за рахунок функціональності; іншими словами, якщо вам не потрібна якась функціональність для конкретного додатка, вимкніть її.


Найбільш помітний ефект мають такі параметри:



Використання NSFDB2 (збереження Domino-даних в базі даних DB2) не сприяє підвищенню продуктивності і зазвичай трохи повільніше, ніж традиційний NSF-файл. Мета NSFDB2 – додаткова функціональність, а не підвищення продуктивності.


Повнотекстовий індекс може зажадати багато місця на диску, але зазвичай це себе виправдовує. Операції пошуку в агентських додатках виконуються швидше, і при відсутності такого індексу користувачі змушені застосовувати більш повільні методи пошуку, що навантажують сервер і видають результати істотно пізніше.


Примітка. Нове властивість бази даних в Notes версії 8.0 дозволяє відключити “повнотекстовий” пошук в базі даних, якщо вона не має повнотекстового індексу. Зазвичай це непогана ідея, навіть якщо повнотекстовий індекс є; таким чином гарантується, що при випадковому видаленні індексу користувачі побачать повідомлення, а не просто несподіване погіршення продуктивності без пояснень.


Ще одна дія, яку можна виконати на рівні бази даних, знаходиться не в діалоговому вікні властивостей, а в діалоговому вікні ACL. Обмеження доступу користувачів для створення персональних уявлень і папок зменшує навантаження на північ (див. малюнок 1).


Рисунок 1. Діалогове вікно ACL

Якщо зняти позначку з прапорця “Create personal folders / views box”, користувачі все одно зможуть створювати робочі індивідуальні (desktop private) уявлення, але вони будуть зберігатися локально, а не на сервері, тому не будуть сильно впливати на продуктивність програми.


Робочі індивідуальні уявлення впливають на продуктивність, тому що для їх індексації користувачі повинні отримувати дані з сервера в режимі реального часу. Тому інтенсивне застосування робочих індивідуальних уявлень теж може перешкоджати роботі сервера. З цієї причини уникайте автоматичного створення індивідуальних уявлень для користувача з налаштуванням “Private on first use” (Індивідуальне при першому використанні). (Більш детально про це нижче.)


4. Продуктивність формул


Більшість функцій @ Functions працює досить швидко, але є декілька, які обчислюються довше. Пам’ятайте про них і використовуйте розсудливо:



Функції організації циклів на макромові часто використовуються надмірно. Хоча в довідкових документах Domino Designer це не зазначено, майже всі макрофункції, що приймають рядкові аргументи, можуть також працювати зі списком. Наприклад, функція @ Left (x; “,”), в якій x – це список, повертає список, до кожного елементу якого застосована функція @ Left.


Примітка. Раніше функції @UserRoles і @UserNamesList сильно знижували продуктивність, але, починаючи з версії Lotus Notes 6.0, результати роботи цих функцій кешуються.


4.1. @ DbLookup і @ DbColumn


Три головні чинники, що впливають на продуктивність @ DbLookup і @ DbColumn:



4.1.1. Використання кешу


Багато розробники занадто часто використовують параметр “NoCache”, особливо в формулах з ключовим словом. Легко побачити, як це може статися, оскільки під час розробки і початкового тестування ключові слова часто змінюються, і параметр NoCache “змушує їх працювати правильно”.


Однак при нормальному використанні ключові слова в додатку зазвичай не змінюються щодня. Деяка затримка доступності нових значень для користувачів є прийнятним компромісом для поліпшення продуктивності. Використовуйте NoCache тільки в разі реальної необхідності.


Є три варіанти кешування:



4.1.2. Вибір коректного подання для операції пошуку


Іноді досить ефективне подання все-таки не є найкращим варіантом для функцій @ Db. Наприклад, @ Unique (@ DbColumn (“”: “NoCache”; “”: “”; “InvoicesByCompany”; 1)) має декілька проблем:



Останній момент особливо важливий, оскільки операція пошуку для стовпця, прекрасно працює з сотнею документів тестових даних, може швидко стати неефективною, як тільки ви почнете використовувати додаток на практиці з тисячею документів. Особливо це проявляється в тих випадках, коли програма використовується на сервері – передача повного вмісту стовпця подання по мережі на робочі станції користувача займає час. Читання уже унікальних значень з уявлення виконується значно швидше.


Примітка. Параметр “Generate unique keys in index” (генерувати унікальні ключі в індексі) може розглядатися як альтернатива категоризованих стовпцях для отримання списку унікальних значень, але він має негативну сторону, що робить його непридатним для такого використання.


Також поганою ідеєю є операція пошуку для довго індексується уявлення і особливо для подання, що використовує @ Today або @ Now в своїй формулі вибірки або формулою стовпця. Якщо вам потрібно знайти тільки документи з конкретною датою, то замість використання @ DbColumn для подання, що містить тільки такі документи, використовуйте @ DbLookup для подання, яке містить усі документи, відсортовані по даті, і надайте дату в якості ключа перегляду.


4.1.3. Уникайте повторюваних операцій пошуку


Функції @ Db можуть використовуватися з різних причин. Ось найбільш поширені:


Повторення у формулі






@If(@IsError(@DbLookup(“”: “NoCache”; “”; “SomeView”; CustID; 3);
“”;
@DbLookup(“”: “NoCache”; “”; “SomeView”; CustID; 3))

Ця формула не тільки використовує NoCache там, де це необов’язково, але і виконує перегляд двічі там, де потрібно робити це тільки один раз. Ось дві альтернативи:






_tmp := @DbLookup(“”; “”; “SomeView”; CustID; 3);
@If(@IsError(_tmp); “”; _tmp)

або






@DbLookup(“”; “”; “SomeView”; CustID; 3; [FailSilent]) 
 

Зайвий пошук ключового слова в режимі читання


Коли документ відкривається для перегляду, для деяких типів полів з ключовими словами, клієнтське додаток Notes не потребує знанні списку варіантів. Очевидними винятками є поля прапорців і залежних кнопок, в яких всі варіанти відображаються навіть в режимі читання, і всі поля, які використовують синоніми ключових слів (“Display text / value”), оскільки документ зберігає тільки “значення”, а форма повинна знати, що відображати в “Display text”.


В інших ситуаціях, тим не менш, записуйте формули ключових слів так, щоб відкласти пошук до реальної потреби в списку варіантів:






_t := @If(@IsDocBeingEdited; @DbColumn(“”; “”; “Customers”; 1);
@Return(@Unavailable));
@If(@IsError(_t); “”; _t)

Повертаючи @ Unavailable в режимі читання, формула вказує формі виконати запит знову, якщо їй в подальшому потрібно список варіантів. Це відбувається в тому випадку, коли користувач переходить в режим редагування і курсор потрапляє в це поле.


Тому не тільки уникайте виконання операцій пошуку, коли користувач всього лише переглядає документ, але також розосереджувати затримку по процесу редагування документа, вісім напівсекундного затримок менш дратують, ніж одна четирехсекундная. І якщо користувач не поміщає курсор у це поле, він взагалі не повинен чекати завершення операції пошуку.


Кілька операцій пошуку там, де можна використовувати одну


Припустимо, що є ідентифікатор клієнта CustID, що зберігається в документі “invoice” (рахунок), і ви хочете використовувати цей ідентифікатор для пошуку та відображення імен клієнтів, їх адрес та імен покупців для контактів. У вашій формі є кілька полів Computed for Display (обчислюється для відображення), кожне з яких містить формулу, що використовує функцію @ DbLookup (“”; “”; “CompanyByID”; CustID; x), де x – це номер стовпця або ім’я поля.


Краще мати один стовпець, що містить всі необхідні значення, які потім можна використовувати для отримання значень індивідуальних полів, тобто формула стовпця може виглядати так:






CustName : StreetAddress : (City + ” ” + State + ” ” + Zip) : PurchasingContact
 

У формі додайте одне приховане поле Computed for Display під назвою CustDetails:






@DbLookup(“”; “”; “CompanyByID”; CustID; 4) 
 

(Передбачається, що комбінованим стовпцем є стовпець 4). Потім можна було б використовувати цю формулу для відображення імені:






CustDetails[1] 
 

і т.д.


Повтор операцій пошуку при оновленні


Припустимо, що вам потрібно підставити ім’я менеджера клієнта в обчислюване поле при складанні форми, наприклад:






@DbLookup(“”; “VOLE1”: “EmpData.nsf”; “EmpByName”; @Name([CN]; @Username);
“Manager”)

Обчислювані поля перераховуються при кожному оновленні форми. Багато форм оновлюються часто (оскільки дозволений параметр поновлення полів при зміні поля ключового слова), тому тут може ховатися причина істотного зниження продуктивності. Більш вдалим варіантом було б використання поля “Computed when Composed” (обчислюється при складанні).


Якщо поле в документі зберігати не потрібно (пам’ятайте, що зберігаються поля – store fields – зберігати не потрібно!), Можна визначити їх як Computed for Display (обчислювані для відображення), але в цьому випадку виконайте наступне, для того щоб виключити повторення операцій пошуку при оновленнях:






@If(@IsDocBeingLoaded;
@DbLookup(“”; “VOLE1”: “EmpData.nsf”; “EmpByName”; @Name([CN];
@Username); “Manager”);
@ThisValue)

Призначення послідовних номерів за допомогою @ DbColumn


Це часто зустрічається помилка. Коли розробникам потрібно створити унікальний ідентифікатор для кожного документа, вони часто роблять це шляхом додавання “1” до номера останнього існуючого документа, тобто використовують приблизно таку формулу:






tmp := @DbColumn(“”:”NoCache”; “”; “RequestsByNumber”; 1);
nextNumber := @If(tmp = “”; 1; @ToNumber(@Subset(tmp; -1)) + 1);
@Right(“000000” + @Text(nextNumber); 7)

Це дійсно поганий прийом. У міру зростання числа документів функція @ DbColumn виконується все довше і довше. Крім того, вона насправді не гарантує унікальність ідентифікаторів при роботі з додатком декількох користувачів, особливо якщо є декілька реплік.


При збереженні номера, призначеного документу, він не буде доступний до завершення цієї операції, що незручно. Оскільки він призначається при формуванні документа, створення і збереження документа з таким же номером ким-небудь ще займе багато часу.


Слід переглянути ваші вимоги. Люди часто хочуть використовувати послідовну нумерацію там, де для програми насправді потрібен тільки унікальний ідентифікатор, який не обов’язково повинен бути числовим. Погляньте на функцію @ Unique, яка генерує досить короткий значення, майже точно є унікальним (унікальність можна гарантувати шляхом виконання додаткових дій, наприклад призначення кожному користувачеві унікального “суфікса”, для чого часто використовуються їхні ініціали).


Якщо ви вирішите, що послідовна нумерація дійсно необхідна, прочитайте статтю developerWorks “Генерування послідовних чисел в реплицируемой додатках”, в якій розглядається один з методів її ефективної реалізації. Додаткова інформація на цю тему буде приведена в підготовлювану статті developerWorks.


5. Проектування форм


У даному розділі ми розглянемо деякі типові проблеми, про які варто згадати.


5.1. Не використовуйте обчислювані поля, якщо працює Computed for Display


Оскільки збереження полів уповільнює роботу програми, має сенс уникати збереження значень, якщо їх можна легко обчислювати при необхідності. Тут має місце компроміс – обчислюване поле не перераховується при відкритті документа в режимі читання, тому, якщо формула є повільною, краще зберігати її для поліпшення продуктивності в режимі читання (з іншого боку, це означає також, що поле може бути застарілим).


Але безумовно ніколи не застосовуйте обчислюване поле, яке просто повторно відображає значення іншого поля – в цьому випадку будуть зберігатися дві копії однієї і тієї ж інформації.


5.2. Сотні полів


Самою типовою причиною наявності великої кількості полів в одній формі є відображення таблиці з декількома рядками і стовпцями, а також з полем у кожній клітинці таблиці. Це важка ситуація, оскільки даний спосіб є найпростішим для реалізації такої функціональності.


Проте є альтернативні способи роботи з таблицями значень. Найбільш очевидний спосіб – помістити таблицю в полі з форматованим текстом (rich text field) і дозволити користувачам вводити все, що вони побажають (використовуйте @ GetProfileField у формулі поля з форматованим текстом за замовчуванням для читання “початкової” таблиці з документа profile). Негативним моментом є те, що користувачі не можуть отримати підказки при заповненні комірок, які можна було б реалізувати за допомогою списків ключових слів, перетворень та перевірок коректності вводяться значень в окремих полях. Але іноді це допустима альтернатива.


Є також кілька доступних засобів і методик редагування таблиць по одному рядку в діалоговому вікні та відображення результатів у таблиці. Наприклад, приклади Domino Design Library в Lotus Sandbox містять набір елементів проектування, які можна використовувати для редагування та відображення даних в таблицях, не реалізуючи поле для кожного осередку. Детально ця система описана в документі “Table Editor” бази даних по документації. Її реалізація займає деякий час, але продуктивність вражає.


Іноді зустрічаються форми, що містять багато полів, які залишаються порожніми в більшості документів. Наприклад, 5% документів потребують розділі “regulatory approval” (офіційний дозвіл), що містить 50 полів. В інших 95% документах це місце буде витрачатися даремно, а продуктивність знижуватися через збереження всіх цих порожніх полів.


В цьому випадку краще було б мати дві різні форми – головну з полями, потрібними завжди, і окрему форму “Regulatory Approval”, пов’язану з оригінальним документом і створювану тільки за потребою. Це саме той випадок, коли краще мати кілька додаткових документів, щоб виключити велику кількість додаткових полів.


Пам’ятайте про багатозначних полях. Замість застосування п’яти полів, що дозволяють користувачеві вводити п’ять окремих значень, використовуйте одне поле, що дозволяє вводити кілька значень. Немає обмеження на кількість елементів (якщо ви не вибрали застосувати його), а одержувані значення набагато легше використовувати в уявленнях і формулах.


Примітка. Якщо програма вже працює повільно через занадто великої кількості полів, редагування елементів проектування поодинці не дасть великого приросту швидкості; потрібно написати агенти для перегляду всіх існуючих документів і видалення додаткових елементів, уже присутніх в них. Для спрощення цієї процедури доступні продукти бізнес-партнерів. Однак якщо ваше зміна є серйозною реорганізацією, такі агенти можуть бути досить складними. Ви заощадите час, якщо передбачте все заздалегідь і будете робити все правильно з самого початку.


5.3. Зайва графіка


Деякі форми перевантажені графічними елементами і використовують великі побітових зображення для фонового малюнка і велика кількість декоративних штучок. Завантаження великих зображень забирає час і пам’ять кешу елементів форми. Час також витрачається на їх промальовування при перегляді форми. Деяка обережність при створенні форм може призвести до професійного зовнішнього вигляду без істотного зниження продуктивності. Ось деякі поради:



5.4. Збережені форми


Не використовуйте зберігаються форми. Просто не використовуйте.


5.5. Автоматично оновлювані поля


Параметр форми “Automatically refresh fields” (автоматично оновлювати поля) повинен використовуватися рідко. Він призводить до досить частого оновлення форми під час редагування, викликаючи затримки при перерахунку обчислюваних полів і формул вхідного перетворення. Звичайно краще використовувати параметр рівня поля “Refresh on keyword change” (оновлювати при зміні ключового слова) або події поля Onchange або Onblur для виконання оновлення тільки при необхідності.


5.6. Зайва кількість спільних елементів дизайну


Форми можуть черпати інформацію з інших елементів дизайну, наприклад джерел зображень, загальних полів, загальних дій, підформу, ієрархічних структур, таблиць стилів, бібліотек сценаріїв. Цілком можливо, що відкриття одного документа викличе читання інформації з дюжини елементів дизайну, крім форми, що займає деякий час. Перевага загальних елементів дизайну полягає в тому, що вони полегшують обслуговування додатки. Недолік – доступ до кількох джерел під час завантаження виконується довше.


Lotus Notes підтримує кеш інформації про дизайн, тому її не потрібно читати з оригінальних елементів дизайну кожен раз, однак час початкового завантаження може бути проблемою. Кешування означає також, що використання загальних елементів дизайну може підвищити продуктивність, якщо одна і та ж підформу або зображення використовуються в багатьох інших формах.


Спільні дії не позначаються негативно на продуктивності, оскільки є тільки одне зауваження по дизайну, що стосується спільних дій, тобто ви можете включити декілька за ціною одного. Загальні стовпці уявлення не впливають на продуктивність.


Через переваг в обслуговуванні, рекомендується знімати елементи дизайну з загального використання тільки після виконання інших дій, після яких продуктивність все одно залишилася неприйнятною.


6. Подання


Неефективні і непотрібні уявлення можуть приводити до затримок з наступних причин:



Ще однією причиною повільного відкриття уявлень є велика кількість документів в базі даних. При відкритті подання Lotus Notes перевіряє наявність будь-яких документів, змінених після часу останнього оновлення індексу подання. Чим більше документів є, тим більший час займає ця перевірка, навіть якщо повернутим відповіддю буде “ні”.


6.1. Функції @ Now або @ Today в уявленнях


Багато було написано про те, як реалізувати уявлення, засновані на дату / час, без використання @ Today або @ Now. Одним із прикладів є стаття на Web-сайті служби підтримки IBM Techdoc “Подання із застосуванням дати / часу в Notes: які є варіанти? “, в якій розглянуті альтернативні способи створення таких уявлень.


Давайте обговоримо кілька додаткових моментів. По-перше, часто повторюваний рада про використання @ TextToTime (“Today”) є неповним. Само по собі це працює тільки на початку. Необхідно виконати додаткову роботу для коректної поведінки цієї функції.


Чому? Зазвичай при відкритті подання Lotus Notes переглядає “індекс вистави” (view index), відсортований список документів і значень рядків у поданні, і перевіряє тільки документи, створені або змінені після часу останнього оновлення індексу. Це робиться для того, щоб визначити, чи потрібно їх додати чи видалити з подання, або перерахувати значення стовпців. Якщо такі документи відсутні, процес виконується дуже швидко.


Однак якщо використовується @ Today, старий індекс уявлення більше не буде корисний. Наприклад, припустимо, що є наступна формула вибору:






SELECT Status = “Processing” & DueDate <= @Today
 

Документи можуть додаватися в це подання, навіть якщо вони не змінилися, оскільки змінилося значення @ Today після останнього використання уявлення. Тому при кожному використанні цього подання Lotus Notes скасовує старий індекс і шукає всі документи в базі даних, для того щоб визначити, чи належать вони цим поданням, а також для перерахунку значень стовпців.


При використанні @ TextToTime (“Today”) замість @ Today можна “перехитрити” механізм індексації подання. Прийміть наші вітання. Lotus Notes буде повторно використовувати старий індекс і перевіряти тільки змінені документи. Це збільшує швидкість, але, на жаль, призводить до некоректних результатів, оскільки при змінах @ Today необхідно знову переглянути всі документи.


Припустимо, що є стовпець, який відображає червоний знак оклику, якщо документ “запиту” все ще залишається відкритим після закінчення трьох годин (тестування і порівняння з @ Now). Така ситуація може статися, навіть якщо подання використовувалося п’ять секунд тому. Хоча з @ Today добре було б просто оновлювати індекс уявлення не так часто.


Можна дійсно робити це, використовуючи параметри індексації подання у вікні Property подання. У закладці Advanced options можна вказати, що дане подання оновлюється “Auto, at most every x hours “(автоматично, не частіше одного разу на x годин), де x – це вказане вами число. Перевага полягає в дуже швидкому відкритті вистави. Недолік – уявлення не відразу відображає зміни навіть для змінених документів. Користувач повинен вручну оновлювати подання, щоб побачити останні дані.


Іншим популярним альтернативним способом є створення запланованого агента (scheduled agent), що виконується щоночі і оновлюючої формулу вибору подання (використовуючи метод NotesView.SelectionFormula), для того щоб вона містила формулу вибору дня. Наприклад, такий агент може містити вираз:






view.SelectionFormula = {SELECT Status=”Processing” & DueDate=[} & Today & {]} 
 

Але цей спосіб має деякі недоліки:



Ще одним рішенням є використання для користувача інтерфейсу. Наприклад, замість вистави “відкрити прострочені запити”, можна було б використовувати вистава “відкрити запити за терміном виконання “, для того щоб прострочені запити йшли першими в поданні. Їх легко можна знайти, а уявлення відкривається значно швидше.


У деяких випадках доречно використовувати папку для відображення групи документів, категоризованих за датою. Щонічний агент може заповнювати папку документами, відповідними цієї дати, а параметри доступу до цієї папки можуть забороняти ручне зміна користувачем її вмісту. Це невдалий вибір, якщо вміст папки повинно змінюватися протягом дня при редагуванні документів (можна також справитися з цим, використовуючи спеціальне кодування, хоча воно є дещо громіздким).


6.2. Необов’язкові подання


Багато програми працюють повільно через наявність великої кількості уявлень. Видалення будь-якого необов’язкового подання принесе користь. Це відіб’ється на продуктивності сервера, а не конкретного додатка.


Примітка. Проектувальник бази даних не обов’язково має доступ для перегляду всіх уявлень. Користувальницькі вистави “Server private” та інші уявлення зі списком читачів, в який не входить розробник, є невидимими, але вони все одно впливають на продуктивність. Адміністратор сервера може побачити ці уявлення, використовуючи режим “Full access administration”.


Установки оновлення уявлень за замовчуванням (Auto after first use, Discard index after 45 days – автоматичне при першому використанні, скидання індексу після 45 днів) означають, що індекси уявлень, які не використовувалися 45 днів, скидаються і більше автоматично не оновлюються сервером. При цьому їх вплив на продуктивність мінімально. Однак наявність уявлень в ієрархічному списку означає, що ймовірно хтось буде іноді використовувати їх ненавмисно, виконуючи пошук підходящого.


Отже, можна не тільки поліпшити продуктивність, але також забезпечити набір уявлень, який буде менше бентежити користувачів (і який обмежений тільки необхідними варіантами вибору, призначеними для конкретних задач), і назвати їх таким чином, щоб користувачі визначали відповідний їм без серйозного пошуку.


Часто уявлення створюються для спеціального одноразового використання, і не існує процесу для реєстрації того, хто запитує їх, хто використовує і коли їх можна безпечно видалити. Часто вони є уявленнями “Server private”, видимими тільки людині, що створив їх, але все одно впливають на продуктивність (якщо потрібно побачити ці вистави, адміністратор сервера може використовувати режим “Full access administration”).


Ми рекомендуємо використовувати поле Comment (коментар) подання для опису завдання, для якої воно було створено, користувачів, які використовують його, дати “старіння”, після якої його можна видалити. Тоді, якщо виникне питання про необхідність будь-якого подання, буде хоча б відомо, кому його задати. Якщо ви хочете видалити уявлення і подивитися, чи буде хтось протестувати, перемістіть його в іншу базу даних, що не містить документів, просто для того, щоб мати резервну копію, яку при необхідності можна буде відновити в основній базі даних.


Часто додаток містить уявлення, які відрізняються тільки сортуванням. Такі уявлення слід комбінувати в одне, що містить стовпці, які можна пересортувати. Хоча витрати на додавання такого типу стовпця великі, вони все одно менше витрат, пов’язаних з наявністю другого окремого подання.


Це особливо справедливо при використанні нового параметра стовпця в Lotus Notes 8.0 “Defer index creation until first use” (відкласти створення індексу до першого використання). Даний параметр відкладає створення індексу для стовпця з пересортовування до тих пір, поки користувач не запросить його. Це призведе до появи тривалої затримки для першого користувача, але якщо більше запитів не буде, всі будуть радіти підвищеної продуктивності.


6.3. Індивідуальні подання


Коли ви будете шукати непотрібні уявлення, пам’ятайте про те, що як розробник ви можете не побачити всі уявлення в додатку. Якщо користувач має індивідуальні уявлення (private views), збережені на сервері, або якщо є загальні уявлення (shared views) зі списком доступу, в який ви не входите, ви не зможете побачити такі вистави в Designer, хоча вони все одно впливають на продуктивність. Адміністратор сервера може обійти перевірки прав доступу, використовуючи режим “Full access administration”, і надати список всіх таких уявлень (і видалити будь-яке, яке ви побажаєте).


6.4. Необов’язкові пересортовування


Оскільки сервер має виконувати додаткову роботу, для того щоб зробити альтернативну сортування негайно доступною за запитом, слід дозволяти пересортовування тільки в тому випадку, коли вона дійсно корисна. Сортування за убуванням і зростанню вважаються двома окремими пересортовування, тому не дозволяйте їх обидві, якщо вони насправді не потрібні. У Lotus Notes 8.0, якщо ви не впевнені в тому, чи буде використовуватися пересортовування, дозвольте параметр “Defer index creation until first use” для такого стовпця.


Зазначимо, що у вас є також варіант переміщення користувача до іншого поданням після клацання лівою кнопкою миші в заголовку стовпця. Це подання вже відсортовано за цим стовпцем, отже, ви можете надати зручну пересортовування без додаткових зусиль (якщо інше уявлення вже існує).


6.5. Необов’язкові стовпці


Заманливо створити стовпець для кожного поля, але не робіть цього. Обмежуйте інформацію в поданні тієї, яка дійсно потрібна користувачеві; екран буде менш захаращений, а все додаток буде працювати швидше і використовувати менший об’єм пам’яті.


6.6. Занадто складні формули


Якщо формула стовпця подання або формула вибору використовує циклічні функції (@ For, @ While, @ Transform) або має довжину більше, ніж, наприклад, 200 символів, не рахуючи коментарів, спробуйте спростити її. Якщо це зробити неможливо, подумайте про переміщення формули в обчислюване поле у ​​формі, для того щоб подання могло звертатися тільки до імені поля. Це особливо корисно для формул, що використовуються в кількох виставах.


Навіть якщо ви не вибираєте використання обчислюваних полів, більшість довгих формул можна спростити, трохи подумавши. Розгляньте варіант використання функції @ Select або @ Replace замість довгих виразів @ If і переглянете логіку роботи для можливого спрощення перевірок за допомогою зміни порядку їх виконання.


Будьте обережні з операторами і @ Functions, що працюють з усіма членами в списку. Немає необхідності писати цикл для багатьох простих маніпуляцій зі строковими списками; наприклад, для отримання перших трьох символів кожного елемента використовуйте функцію @ Left (listfieldname, 3).


Також є “комбінаторні” оператори, такі як * =, які можна використовувати для порівняння всіх комбінацій елементів з двох списків і які допоможуть написати більш лаконічні формули.


Якщо ви програмували на інших мовах, можливо, вам знайомі логічні оператори, що обчислюють тільки ті вирази, які необхідні для визначення значення логічного множення. Наприклад, вираз






Form = “Report” & ( Sections = “Financials” / Total > 10000)
 

спочатку перевіряє, чи є форма звітом, і тільки при істинності цього твердження перевіряє решту вираження. У макромови (і в LotusScript) логічні оператори так не працюють. Завжди обчислюються обидві частини виразу. Тому, якщо обчислення другої частини вимагає великих витрат, можливо краще буде виконати свою власну формулу з “ледачої логікою” наступним чином:






@If(Form = “Report”;  Sections = “Financials” / Total > 10000; @False) 
 

Функція @ If виконується довше, ніж оператор &, але якщо можна використовувати її, щоб уникнути непотрібного обчислення будь-яких витратних функцій, ви виграєте в кінцевому підсумку.


6.7. Зловживання множинної категоризацією


Категорії – це прекрасні елементи. Вони можуть дозволити вказувати документ під кількома заголовками в одному і тому ж поданні, що вельми корисно. Але не перестарайтеся, оскільки перерахування документа в поданні двічі уповільнює уявлення приблизно в два рази. Якщо кожен документ знаходиться в п’ятдесяти категоріях (і якщо це число помножити на кількість документів), бідний сервер повинен буде обчислювати і зберігати занадто багато рядків.


Навіть якщо ви не використовуєте кілька категорій, категоризованих подання працюють повільніше, ніж відповідні їм подання з простою сортуванням. Час залежить від кількості рядків (не документів), а кожен документ і кожен заголовок категорії є рядком.


6.8. Зайва індексація


Діалогове вікно View Properties містить набір параметрів, які керують індексацією подання. Ці параметри використовуються рідко, але вибір відповідного варіанту індексації може мати великий вплив на продуктивність.


Наприклад, припустимо, що база даних містить спеціальні документи ключових слів, часто переглядаються для заповнення списків ключових слів у формі. Такі документи міняються дуже рідко, але інші документи в додатку редагуються постійно.


Нам вже відомо з обговорення функції @ DbLookup, що для пошуку таких документів краще всього використовувати кеш, але все одно треба звертатися до подання перший раз, коли ще відсутні кешовані значення. При цьому Lotus Notes зауважує існування документів, змінених після часу останнього використання уявлення, і витрачає час на перегляд цих документів і виявлення того, що вони не входять до подання.


Подання, що використовується у функції @ DbLookup для значень ключових слів, переіндексувати при кожному його використанні не обов’язково. Для такого подання має сенс вибрати варіант індексації “Auto, at most every x hours” (автоматично, не частіше одного разу на x годин) з відповідним значенням x (див. малюнок 2).


Рисунок 2. Параметри індексації подання



Такі уявлення все одно оновлюються сервером, коли їх ніхто не використовує, але не дуже часто. Іноді “нещасливий” користувач зіткнеться з оновленням індексу. Однак середній час пошуку буде значно менше, і малоймовірно, що який-небудь користувач постраждає від накладних витрат на всі операції пошуку в складній формі. Іншими словами, форма все одно буде відкриватися швидше, ніж у разі використання іншого варіанту індексації.


Якщо подання використовується один день у кожному кварталі для квартального звіту, немає сенсу зберігати індекс 45 днів. Налаштуйте його на скидання після двох днів і розвантажите сервер.


Існують інші ситуації, в яких можна поліпшити продуктивність, вибираючи підходящий варіант індексації. Є сенс подумати про правильному налаштуванні кожного уявлення.


Примітка. Є можливість програмного поновлення індексу в поточному репліці, використовуючи метод NotesView.Refresh. Припустимо, що є індекс, який зазвичай оновлюється рідко, але при збереженні конкретної форми, дані якої беруть участь у поданні, необхідно оновити це подання, для того щоб можна було відразу ж використовувати нові дані. У коді Postsave цієї форми використовуйте метод Refresh для подання. Також можна було б використовувати функції @ Db з ReCache для поновлення кешу специфічних операцій пошуку в цьому поданні.


6.9. Поля Reader


Не існує заміни для полів Reader, якщо вони потрібні, але вони можуть знижувати продуктивність подання. При відкритті подання, яке містить документи з полями Reader, Lotus Notes сканує рядки в пошуках тих, до яких у вас є доступ. Сканування припиняється при наявності достатньої кількості рядків для заповнення екрану. Якщо ви маєте доступ тільки до одного документу, Lotus Notes повинен переглянути кожен рядок, щоб визначити це, що може зажадати досить багато часу.


Є кілька дій, які можна виконати для вирішення даної проблеми:



Не використовуйте поля Reader виключно для навігації, наприклад, як засіб пошуку “своїх” документів, оскільки вони є в поданні єдиними, які можуть бачити користувачі. Якщо інформація в документі не є дійсно приватною, існують кращі способи допомогти користувачам знайти відповідні документи, як описано вище і в наступному розділі.


6.10. Індивідуально при першому використанні


@ UserName і @ UserRoles не дають бажаних результатів при використанні в формулах вибору або формулах стовпців загального уявлення. Це основна причина, по якій розробники створюють уявлення “Private on first use “(індивідуально при першому використанні) для відображення тільки” My Documents “. Ці подання чи зберігаються на сервері, і в цьому випадку впливають на загальну продуктивність програми, або зберігаються в локальному (настільному) файлі користувача.


Настільні (desktop) уявлення не впливають безпосередньо на продуктивність сервера, але коли хтось відкриває одне з них, вона, як і інші вистави, переіндексіруется для відображення останніх змін. Це означає, що комп’ютер користувача повинен запросити з сервера всі документи, змінені після часу останнього використання даного подання. Це може зайняти час і, якщо таку операцію виконав кілька користувачів, сервер може зіткнутися з труднощами, обробляючи численні запити на “передачу всіх даних”.


Зазначимо, що индексируемое подання використовує тільки підсумкові дані, тому великі поля з форматованим текстом і файлові вкладення в даному випадку не є проблемою.


Крім питань продуктивності, індивідуальні уявлення піднімають проблему обслуговування, оскільки для розробника не існує простого способу оновити дизайн індивідуальних користувацьких реплік. Навіть загальні стовпці в даному контексті не працюють, оскільки для їх оновлення людина, яка виконує його, повинен мати доступ до вистави.


Часто можна уникнути використання Private on first use за допомогою функціональності “single category” (одна категорія) уявлень Notes. Наприклад, при відображенні “My Documents” можна використовувати уявлення, категоризаційної документи по власникам, потім або вбудовувати подання до форму або сторінку з формулою “single category”, або використовувати @ SetViewInfo у події Postopen подання для обмеження відображуваної поточному користувачу інформації. Оскільки тут є тільки одне загальне уявлення, загальні витрати на індексацію мінімізуються, і окремий користувач не повинен чекати, як в ситуації з настільним індивідуальним поданням, тому що індекс завжди знаходиться у відносно оновленому стані.


7. Код


Як тільки ви почнете писати код на LotusScript або Java ™, перед вами відкриється цілий новий світ можливостей для створення програм з низькою продуктивністю. Нижче ми розглянемо деякі найбільш часто зустрічаються підводні камені.


7.1. GetNthDocument


Ітерація по колекції з використанням NotesDocumentCollection.GetNthDocument є дуже повільною, замість неї використовуйте GetFirstDocument і GetNextDocument. Існують деякі типи колекцій, для яких GetNthDocument ефективний, але легше просто не використовувати його.


7.2. Занадто багато коду дій у формі або поданні


Якщо у формі, поданні або папці є багато коду дій, і ви пишете код для кожної дії в елементі дизайну (або навіть при використанні загальної дії), зберігається багато коду, який повинен завантажуватися в пам’ять при кожному використанні елемента дизайну.


Основну частину часу буде використовуватися тільки одне або два з багатьох дій, тому завантаження їх усіх є зайвою тратою часу. Якщо дія з’являється в декількох місцях, один і той же код кешується кілька разів, використовуючи пам’ять, яка, можливо, потрібна для інших цілей.


Подумайте про переміщення частини коду дій у додатки-агенти. Це дозволить мати тільки одну копію коду, що завантажується в пам’ять тільки в тому випадку, коли хтось запросить його виконання. Дія кнопки можна написати на макромові для виклику агента за допомогою @ Command ([RunAgent]), тобто разом з елементом дизайну повинен завантажуватися дуже невеликий код.


Це особливо важливо, якщо ви дозволяєте користувачам створювати індивідуальні подання або папки, оскільки код дій буде дублюватися багато раз в їх папках, займаючи простір, і не може бути оновлений, поки користувач вручну не видалить своє індивідуальне уявлення.


7.3. Занадто багато бібліотек сценаріїв


Час, необхідний для завантаження кількох бібліотек сценаріїв в одному і тому ж сценарії, збільшується швидше, ніж в лінійній прогресії. Іншими словами, завантаження десяти бібліотек сценаріїв займає значно більше часу, ніж подвоєне час завантаження п’яти бібліотек, особливо якщо бібліотека використовує (“Use”) інші бібліотеки.


Це може змінитися в майбутньому, але все одно існує один безпрограшний прийом: доступ до двох елементів дизайну виконується довше, ніж доступ до одного елементу, який містить той же обсяг коду. Комбінування часто використовуваних бібліотек сценаріїв економить час завантаження, навіть якщо в деяких випадках ви можете включити код, не викликається в конкретному агента.


7.4. Метод ComputeWithForm


Метод NotesDocument ComputeWithForm є простим способом оновити обчислювані поля в документі без необхідності дублювання коду. На жаль, він також є досить повільним у порівнянні з “Ручним” обчисленням і присвоєнням нового значення поля. Якщо ваш агент працює повільно і ви використовуєте ComputeWithForm, ймовірно, можна значно прискорити його, виділивши цей виклик і помістивши пару рядків коду для присвоєння специфічних полів.


7.5. Автоматично оновлювані вистави


За замовчуванням об’єкт NotesView при використанні реалізує нормальні атрибути поновлення індексації. Наприклад, припустимо, що виконується оновлення колекції документів “Овоч”, і як частина цього процесу, необхідно знайти шкідників цих овочів у виставі “Шкідники” цієї ж бази даних. Але при збереженні документ “Овоч” вважається зміненим.


При переході до наступного документу та виконанні пошуку у виставі “Шкідники” Lotus Notes зауважує, що індекс уявлення не актуальне, і оновлює його. Вам відомо, що виконане зміна не вплинуло на виставу “Шкідники”, але Lotus Notes не знає про це, поки не протестує змінений документ.


В цьому випадку має сенс використовувати властивість AutoUpdate подання NotesView для вказівки системі Lotus Notes не турбуватися про індексацію подання до тих пір, поки ви явно не запросите її при допомогою методу Refresh. Це значно прискорить роботу додатка.


Також можна використовувати цей метод навіть у тому випадку, якщо виконувані зміни впливають на вміст NotesView. В даному випадку вам повинно бути відомо, що ці зміни не матимуть відношення до того, що ви робите. Наприклад, відомо, що оновлення видалить документ з уявлення, але це не важливо, оскільки ви переходите до наступного документу.


7.6. Невдале застосування ефективних методів, заснованих на колекціях


Клас NotesDocumentCollection має кілька методів, назви яких закінчуються на “All”, що надають спосіб виконувати дії над всіма документами в колекції. Зустрітися з цими методами, оскільки вони працюють набагато швидше, ніж ітерація по колекції і робота з кожним документом окремо (природно, якщо не потрібно виконувати декілька дій з кожним документом, і потім, можливо, швидшим буде виконання ітерації для збереження кожного документа тільки один раз).


7.7. Повторювані витратні операції


Деякі методи і властивості у вбудованих класах є досить повільними. Ваш код буде працювати швидше, якщо уникати періодичного використання цих функцій, коли це не потрібно. Наприклад, припустимо, що в міру обробки документів у колекції для кожного з них необхідно використовувати одне з полів як значення операції пошуку для добування інформації з іншого уявлення:






Dim view As NotesView
Set docCur = coll.GetFirstDocument
Do Until docCur Is Nothing Set view = db.GetView (“CustomersByID”) “Ось! Не робіть цього в циклі!
Set docCust = view.GetDocumentByKey(docCur.CustID(0), True)

Set docCur = coll.GetNextDocument(docCur)
Loop


Якщо б у цьому прикладі коду coll містила 1000 документів, ми викликали б витратний метод GetView 1000 раз. Даний код буде працювати значно швидше, якщо просто поміняти розташування рядків Do Until і Set view, Так щоб GetView викликався тільки один раз.


Профілювання агентської програми є хорошим способом пошуку таких моментів. Воно розглядається в статтях developerWorks “Діагностика продуктивності додатків, частина 1. Діагностика методики та поради щодо використання коду“І”Діагностика продуктивності додатків, частина 2. Нові інструментальні засоби в Lotus Notes / Domino 7“.


7.8. Збереження не змінилися документів


Згадайте, що одним з факторів, що впливають на продуктивність, є “збовтування” (churn), тобто частота зміни документів. При написанні програм-агентів для обробки документів спробуйте уникати зайвого збереження змін в документі. Перед присвоєнням значення елементу перевірте, чи не має вже елемент це значення. Якщо в кінцевому підсумку ви нічого не змінили, не викликайте метод Save. Часто можна використовувати методи пошуку для фільтрації з колекцій документів, які не потрібно обробляти.


Агентські додатки можуть працювати довше, якщо постійно перевіряти елементи з метою визначення необхідності їх зміни, а, можливо, й ні, оскільки збереження документа виконується набагато довше, ніж порівняння інформації в пам’яті. Але в будь-якому випадку інші частини вашої програми будуть працювати ефективніше, від реплікації до індексації уявлень і до повнотекстової індексації.


Виняток непотрібних збережень також зменшує шанс виникнення конфл

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*