• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

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

    Запись на курс до 25 апреля. Получить промодоступ ...

Форма Грузится Долго

  • Автор темы Chron
  • Дата начала
C

Chron

Всем привет... У меня небольшая проблемка возникла (ну как небольшая, меня лично изрядно напрягает).... в общем, существует база... в нее ломяться как из внутренней сети напрямую, так и из подразделений через модемы, випнет координаторы и т.п. Дело в том, что у тех, кто сидит внутри сети проблем с базой нет, а у внешних пользователей они есть... а именно то, что долго грузится одна форма... проверял дебагером, логика заступоривается именно на диалогбоксе, которая собственно говоря эту форму вызывает... примерно две минуты виснет прежде, чем вывести форму... возможны конечно варианты со скоростью, но согласитесь задержка в 30 мс вряд ли позволит являться форме целых две минуты... И хотелось бы совета, может есть какие-то лотус-утилиты, которые позволяет отследить в каком месте форма так долго загружается... возможно я как-то ее оптимизирую, или возможно вы сами что-нибудь мне предложите, если сталкивались с подобным... Спасибо...
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
На той форме много вычисляемых полей?
Я конечно не силен, но такое ощущение, что форма, как раз, все эти поля высчитывает долго.

Если есть возможность открой форму без dialogbox, посмотри сколько грузиться.
Без dialogbox поможет легкий таймер.

Делаешь в событиях формы:
Код:
Declarations:
Dim dtB as NotesDateTime
Dim dtE as NotesDateTime

Initialize:
set dtB = new NotesDateTime("")
set dtE = new NotesDateTime("")
call dtB.SetNow()

PostOpen:
call dtE.SetNow()

msgbox "" & dtE.TimeDifference(dtB) 'Время в секундах

Как ты понимаешь, тебе откроется message со временем открытия.

А как ты форму диалога вызвываешь и для чего?

Через script или на собаках?
Для заполнения или отображения информации просто?
 
C

Chron

savl, на скрипте вызывается... время вызова без диалогбокса такое же... я тут проверил, в итоге долго отрабатывается вот этот цикл:
Код:
Set viewAD = b.GetView("($VIMGroups)") ' доступ к виду с Группами	
Set docAD = viewAD.GetFirstDocument ' к первому документу вида Группы

Do While Not docAD Is Nothing ' проверяем все документы вида Группы
ListGroup = docAD.Members				
Forall ii In ListGroup
If nameS.Canonical = ii Then
' создаем список групп, в которых активный юзер является членом						
If 		Iselement ( ListGroupStr ( docAD.ListName(0) ) ) Then
Else
ListGroupStr(docAD.ListName(0)) = 0								
End If
Else
End If
End Forall
Set docAD = viewAD.GetNextDocument(docAD)	
Loop
End If
End Forall

Возможно его как-то оптимизировать?

Следует отметить, что дочерних серверов много, а адресная книга общая... и там групп мерено-немерено просто...
 
T

turumbay

Возможно его как-то оптимизировать?
А к чему там последний Forall? У вас есть еще и внешний цикл???
Для начала - стоит поменять местами внешний и внутренний циклы( если конечно внешний не по списку баз ). Приведите код целиком.

Откуда берутся names? Я так понимаю, что это не текущий пользователь, а некоторое произвольное нотес-имя?
Какую задачу решает код?
 
F

FixeR

Какую задачу решает код?
ListGroupStr - насколько я понял, это list, список групп, в которых состоит пользователь.

Chron,
Если это так, то Вам нужна функция @UserNamesList.
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
Если действительно нужно получить просто список групп, в которых состоит пользователь, то я соглашусь с FixeR. Эта функция его выдаст, так же есть аналог на скрипте: NotesSession.UserGroupNameList
Но за аналогичность работы не ручаюсь, надо проверить.
 
T

turumbay

ListGroupStr - насколько я понял, это list, список групп, в которых состоит пользователь.
Вопрос был не "что делает?", а "зачем делает?". Если бы автор рассказал, какую задачу решает - то можно было бы подумать над альтернативными способами прохождения квеста.
Смущает хвост от некоего внешнего цикла - есть подозрение, что группы разворачиваются не для текущего юзера, а для некоего списка notes-имен(т.е. UserGroupNameList не катит) . Если предположение верно - то самая очевидная оптимизация - вывернуть циклы наизнанку и итерировать вьюху ровно один раз. Кроме того, можно попробовать заменить клиентский поиск на серверный, т.е. вместо обхода всей вьюхи юзать db.search. Дальше можно думать о кешировании результатов функции, например в профайле. В общем вариантов масса, но нужно понимать контекст задачи....
 
C

Chron

Вопрос был не "что делает?", а "зачем делает?". Если бы автор рассказал, какую задачу решает - то можно было бы подумать над альтернативными способами прохождения квеста.
Привожу полный кусок кода...
Код:
books = session.AddressBooks ' получаем доступ ко всем адресным книгам на текущем сервере
Forall b In books
If b.IsPublicAddressBook Then
Call b.Open( "", "" )

Set viewAD = b.GetView("($VIMGroups)") ' доступ к виду с Группами	
Set docAD = viewAD.GetFirstDocument ' к первому документу вида Группы

Do While Not docAD Is Nothing ' проверяем все документы вида Группы
ListGroup = docAD.Members				
Forall ii In ListGroup
If nameS.Canonical = ii Then
' создаем список групп, в которых активный юзер является членом						
If 		Iselement ( ListGroupStr ( docAD.ListName(0) ) ) Then
Else
ListGroupStr(docAD.ListName(0)) = 0								
End If
Else
End If
End Forall
Set docAD = viewAD.GetNextDocument(docAD)	
Loop
End If
End Forall
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
Думаю, что можно заменить этот Forall

Код:
			  Forall ii In ListGroup
If nameS.Canonical = ii Then
' создаем список групп, в которых активный юзер является членом						
If		 Iselement ( ListGroupStr ( docAD.ListName(0) ) ) Then
Else
ListGroupStr(docAD.ListName(0)) = 0								
End If
Else
End If
End Forall

на

Код:
k = ArrayGetIndex(ListGroup,nameS.Canonical)
if no Isnull(k) then
If Not Iselement ( ListGroupStr ( docAD.ListName(0) ) ) Then
ListGroupStr(docAD.ListName(0)) = 0								
End If
end if

своеобразное ускорение даст, так как перебора имен не будет.
Но это для текущей сессии работает, так что можно попробывать UserGroupNameList и сравнит результаты.
 
N

nvyush

Chron
Некоторого (небольшого) ускорения можно добиться, заменив
Код:
Do While Not docAD Is Nothing
на
Код:
Do Until docAD Is Nothing

А конструкция
Код:
		If b.IsPublicAddressBook Then
Call b.Open( "", "" )
разве работает? Если верить справке, то "The database must be open to use this property" (свойство IsPublicAddressBook)
Examples: IsPublicAddressBook property
Код:
 Forall db In session.AddressBooks
Call db.open("", "") ' Must open database
If db.IsPublicAddressBook Then
'...
 
C

Chron

своеобразное ускорение даст, так как перебора имен не будет.
Но это для текущей сессии работает, так что можно попробовать UserGroupNameList и сравнит результаты.
Быстрее работать к сожадению не стал...
В случае с UserGroupNameList
Код:
ListGroupStr = session.UserGroupNameList

и этого достаточно?
 
N

nvyush

Код:
и этого достаточно?
Скорее, Вам нужно использовать
UserNamesList = Evaluate({@UserNamesList})

Добавлено
Гляньте ещё сюда:
link removed

И подумайте над возможностью кэширования списка.
 
N

nvyush

Пардон, а сам Evaluate разве не есть источник тормозов?
Если аргумент Evaluate — строковая константа (как в данном случае), то формула компилируется на этапе компиляции скрипта и тормозов меньше.
 
T

turumbay

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

У вас проблема в том, что вы каждый раз скачиваете на клиента адресную книгу. То тех пор, пока будет проход по всем документам Group всех АК - ничто вас не спасет.
Еще раз: какую задачу-то решаете? Откуда nameS берется? Это текущий юзер или таки нет? Можно ли выделить небольшое множество значений nameS, для которых выполняется 80% всех вызовов?
 
O

Omh

Ну и если идёшь по view, то перед началом прохода взведи
Код:
view.AutoUpdate = False
, после -
Код:
view.AutoUpdate = True
. Очень сильно влияет на быстродействие.
 
T

turumbay

Ну и если идёшь по view, то перед началом прохода взведи
Код:
view.AutoUpdate = False
, после -
Код:
view.AutoUpdate = True
. Очень сильно влияет на быстродействие.
По жизни - да, но не в данном случае. Здесь 99% времени выполнения - это получение вьюхи и документов ( getView и getNextDocument ) соотвественно.
AutoUpdate особенно хорош, когда бежим по индексу вида и не читаем из него документы ( т.е. используя только ViewEntry )
 
C

Chron

Слущайте... я тут глянул... файл names.nsf не проиндексирован... это может как-то повлиять на перебор вьюшки?
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!