Lotus Notes Development (client): Performance Consideration

  • Автор темы nor
  • Дата начала
Доброе время суток. Некоторое время тому назад я столкнулся с проблемой производительности моего одного проекта, который за последние 12 месяцев значительно возрос в плане функционала и клиентской базы. Начали потупать жалобы от пользователей, что все "тормозит". Пришлось разбирать куски кода "с секундомером в руках", выявлять "слабые звенья" и менять код или логику на более производительные. В результате приложение стало работать значительно быстрее и в целом более стабильнее.
Вот некоторый короткий перечень положений, которыми я руководствовался в процессе этой работы. Надеюсь этот список будет полезен новичкам в Lotus программировании. Приглашаю всех поделиться своими замечаниями и собственными наработками по теме.

- Display images after loading.
- Don't maintain unread marks.
- Optimize document table map.
- Don't overwrite free space.
- Don't support specialized response hierarchy (if there are no responses in a database).
- Use LZ1 compression for attachments.
- Don't allow headline monitoring.
- Soft delete expire time in hours to 48 (if soft deleton is set).
- Limit enrties in $UpdatedBy fields to 25.
- Limit enrties in $Revisions fields to 25.
- Minimize deletion stubs.
- Adjust full-text index options.
- Define Anonymous in the ACL.
- Limit use of 'Strong Encryption'.
- Adjust scheduled agents.
- Do not allow use of stored forms in a database.

- Do not have too many views.
- Remove private views every time when a user closes a db.
- Never use time/date sensitive formulas (selection or column formulas) in views.
- Separate views for end users and for your script.
- Do not complicate a view (avoid complex selection formulas, many categories, many columns, etc.).
- Hidden views should be as simple as possible (no column sorting, no font color, etc.)
- Avoid adding many column sorting arrows to a view.
- Use view.Autoupdate = False in your code every time you retrieve a NotesView object.
- Store the proper computed data in fields on a form to display it in a view rather than making the computation in columns of the view.
- The view set as the default view should be small in size.
- Minimize the use of 'GetView' method of NotesDatabase object.

- Do not use 'Automatically refresh fields' option in a form.
- Use temporary variables as placeholders for data (objects, Notes objects) that is expensive to retrieve.
- Do not put much computed fields on a form.
- Use computed, computed for display and computed when composed fields in proper document modes (new, read, edit).
- Do not use large subforms.
- Avoid large or complex tables on a form.
- Disable AutoReload when using the NotesUIDocument object.
- Avoid using Computed and Computed when Composed fields to format fields for display purposes. Use the “Computed for Display” type for fields which are only

used to format data for the UI.
- When many fields in a form contain formulas that evaluate on the same event, it is recommended that a script event be created to replace all the field
- Minimize the use of complex pop-ups within a form.

- Use buttons and picklists instead of drop-down lists when using @DbLookup and @DbColumn formulas.
- Pay attention to 'Cache' and 'Nocache' parameters of @DbLookup and @DbColumn formulas.
- Use one lookup to get multiple fields using @DbLookup and @DbColumn formulas.
- Use column numbers instead of field names in @DbLookup and @DbColumn formulas.
- Make use of the @IsDocBeingEdited and @IsDocumentBeingSaved functions to improve keyword lookup formulas.
- Keyword fields and pop-ups utilizing lookups all evaluate when a document is being opened. To reduce document opening time, place
lookups behind buttons. Button formulas only evaluate when selected.
- Use temporary variables in your formula to save @Db lookup results.
- Use temporary fields (computed for display) in your form to save @Db lookup results.
- Combine required data into one column. Use the @Subset function to parse the results.

- Generally use view.GetAllDocumentsByKey (view.GetDocumentByKey) and db.Search to retrieve a document collection.
- Use the StampAll and RemoveAll methods of NotesDocumentCollection to process a collection of documents.
- Use GetNextDocument instead of GetNthDocument of NotesDocumentCollection object.

- Generally use the For and Forall loops.
- Do not use dynamic arrays so much.
- Do not use an array or list of NotesDocument objects.
- Do not use environment variables.
- Don't Use 'Print' so much.
- Declare your variables.
- Resume out of your error handling blocks.
- Resize arrays infrequently.
- Use variant types only when required.
- Minimize the use of Redim.
- Use back-end objects instead of front-end objects.
- Reuse existing objects, do not repeat them again.
- Do not use 'Arrayappend' method so mach ('Redim Preserve' is MUCH more efficient than many calls to 'ArrayAppend').
- Generally use 'GetDocumentByUNID' method of NotesDatabase object to retrieve a document.
- When accessing a field more than once, get the item once and cache it in a NotesItem variable.


3 915
<!--QuoteBegin-nor+12:09:2007, 12:08 -->
<span class="vbquote">(nor @ 12:09:2007, 12:08 )</span><!--QuoteEBegin-->- Do not use an array or list of NotesDocument objects.
- Do not use environment variables.
- Don't Use 'Print' so much.
[snapback]77943" rel="nofollow" target="_blank[/snapback]​
можете обоснавать эти 3 ?
с остальным полностью согласен

могу добавить, что использовать вместо GetItemValue("MYField") - прямой вызов Doc.MYField(0), имхо быстрее

хорошо расписан @DbLookup
Для: Morpheus

- Do not use an array or list of NotesDocument objects.

If you're working with a large number of NotesDocuments, don't create an array or list of NotesDocument objects -- this uses a lot of memory. Either use a DocumentCollection/NotesDocumentCollection or create an array/list of NoteIDs and access the documents as needed using the NoteIDs.

- Do not use environment variables.

You should generally prefer profile documents to environment variables to store and retrieve user-specific information in a database. It's much more efficient (doesn't require file-system access), and the user information can stay persistent across mutiple workstations.

Each access to an environment variable causes I/O to the NOTES.INI file.
This can have a performance impact if used to excess.
As an alternative, save persistent data in profile documents.
When environment variables must be used, combine all your information
into a single environment variable instead of using many variables. Use
predetermined delimiters to separate your data. The cost of the I/O itself
when accessing the NOTES.INI file is far greater than the amount of data
retrieved during that I/O.
During testing, it was determined that performance savings are proportional
to the number of variables you combine into one. Saving five environment
variables individually took five times longer than saving the five values
together as a single variable. Likewise, saving two took twice as long, and
saving 10 took 10 times as long.

- Don't Use 'Print' so much.

Printing a lot of messages to the status bar or console uses a surprising amount of memory, and it can have a noticible impact on an otherwise fast-running loop. Specifically, the memory used by each Print statement is not released until the entire agent is finished (see IBM Technote 1089676 for details).


Well-known member
Generally use 'GetDocumentByUNID' method of NotesDatabase object to retrieve a document.

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


Что это ? :)
Lotus team
3 346
Для: Kee_Keekkenen
Ага. Я словил глюк (или фичу?), когда вместо ошибки на несуществующем UNID, как положено по хелпу, он выдавал мне несуществующий(?) "нулевой" (время создания нулевое, размер, поля и т.д.) документ. Без ошибок.
В результате стал использовать NotesView.GetDocumentByKey.