O
If Iselement(Listeg(doc.MJ_GRID(0))) = True Then
Forall id In Listeg
If (Listtag(id) = doc.MJ_GRID(0)) And (Cdat(id) < Cdat(doc.CompletedDate(0))) Then
'записываем в наш лист новую дату из дока и стираем элемент с текущим листтагом
Listeg(doc.MJ_GRID(0)) = doc.CompletedDate(0)
Goto label
End If
End Forall
Else
If Iselement(Listeg(doc.MJ_GRID(0))) Then
if Cdat(Listeg(doc.MJ_GRID(0))) < Cdat(doc.CompletedDate(0))) Then Listeg(doc.MJ_GRID(0)) = doc.CompletedDate(0)
Else
Listeg(doc.MJ_GRID(0)) = doc.CompletedDate(0)
End If
Убери
Set doc = coll.GetNthDocument(i)Это очень экспенсив оперейшн.
А ты с секундомером проверь. На 5000 разница будет очень заметная.никогда не замечал...
Function getCollection As NotesDocumentCollection
On Error Goto errhandle
Dim session As New NotesSession
Dim db As NotesDatabase
Dim searchFormula As String
' типа готовимся
Set db = session.CurrentDatabase
searchFormula = {Form = "MotivatedJudgementForm" & (Status= "Completed")}
' получаем коллекцию
Dim collection As NotesDocumentCollection
Set collection = db.search( searchFormula , Nothing , 0 )
' обработка коллекции - просица в отдельный метод
Dim resultList List As NotesDocument
Dim doc As NotesDocument
Set doc = collection.getFirstDocument
While Not doc Is Nothing
Dim existDoc As NotesDocument
Dim key As String
key = doc.ID(0)
On Error Resume Next
Set existDoc = resultList( key )
On Error Goto errhandle
' блок if then else тоже можно вынести в отдельный метод - будет лучше читацо
If existDoc Is Nothing Then
Set resultList( key ) = doc
Else
If existDoc.Date(0) < doc.Date(0) Then Set resultList( key ) = doc
End If
Set doc = collection.getNextDocument(doc)
Wend
' создание коллекции на основе списка. опять же - отдельная песня, не относящаяся к логике функции
Dim resultCollection As NotesDocumentCollection
Set resultCollection = db.Search( "" , Nothing, 0 ) ' создаем пустую коолекцию
Forall result In resultList ' здесь проход по документам в памяти. совершенно не затратно...
Call resultCollection.AddDocument( result )
End Forall
Set getCollection = resultCollection
Exit Function
errhandle:
' пацаны обычно здесь вставляют обработчег - но мы обойдемся....
' Call errHandler.catch( LIB_NAME & "." & Getthreadinfo(1) & ": " & Erl )
Exit Function
End Function
Сорри. Больная тема. Был у мну как-то начальник - упертый идиот...так же как GetItemValue будет быстрее прямого обращения
Dim resultList List As NotesDocument (as NotesDatabase и т.д.)
Вообще, листы объектовмогут при большом кол-ве этих самых объектов привести к оверфлову стека.Код:Dim resultList List As NotesDocument (as NotesDatabase и т.д.)
хочеш цифры есть поиск, обсуждалось сотни раз и эксперементально показывалось.Какой нафиг быстрее?? Цифры в студию!
таки холивар.хочеш цифры есть поиск, обсуждалось сотни раз и эксперементально показывалось.
в остальном - тон попроще, Ваше наболевшее - это лично и только Ваше наболевшее.
Значит мы вынуждены идти на компромис: либо память, либо скорость.
Если заранее можно оценить размер возвращаемой коллекции, то оптимальным по скорости будет приведенный мной вариант.
Три прохода. Третий - в вызывающей процедуре. А можно - за один.Автор уже привел решение. Два прохода по коллекции. Память практически не расходуется.
Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim collection As NotesDocumentCollection
Set db = session.CurrentDatabase
Print "Формируем коллекцию"
Set collection = db.AllDocuments
Dim doc As NotesDocument
Set doc = collection.GetFirstDocument
Dim count As Long
Dim newCollection As NotesDocumentCollection
Set newCollection = db.Search( "" , Nothing , 0 )
While Not doc Is Nothing And count < 500
Call newCollection.AddDocument( doc )
count = count + 1
Set doc = collection.GetNextDocument( doc )
Wend
Print "Поехали"
Dim startTic As Long
Dim seconds As Double
startTic = Getthreadinfo(6)
' Поехали: 3 раза перебрать коллекцию
Call goThroughCollection ( newCollection )
seconds = (Getthreadinfo(6) - startTic) / Getthreadinfo(7)
Print "goThroughCollection Finished. The code ran for " & Format$(seconds, "##0.00") & " seconds."
startTic = Getthreadinfo(6)
' Поехали: перебрать коллекцию, создать массив, два раза пройтись по массиву
Call goThroughArray ( newCollection )
seconds = (Getthreadinfo(6) - startTic) / Getthreadinfo(7)
Print "goThroughArray Finished. The code ran for " & Format$(seconds, "##0.00") & " seconds."
End Sub
Private Function goThroughCollection( i_collection As NotesDocumentCollection )
Dim form As String
Dim i As Long
For i = 0 To 2
Dim doc As NotesDocument
Set doc = i_collection.GetFirstDocument
While Not doc Is Nothing
form = doc.Form(0)
Set doc = i_collection.GetNextDocument( doc )
Wend
Next
End Function
Private Function goThroughArray( i_collection As NotesDocumentCollection )
Dim form As String
Dim docs() As NotesDocument
Dim count As Long
Dim doc As NotesDocument
Set doc = i_collection.GetFirstDocument
While Not doc Is Nothing
Redim Preserve docs( count )
Set docs( count ) = doc
form = doc.Form(0)
count = count + 1
Set doc = i_collection.GetNextDocument( doc )
Wend
Dim i As Long , j As Long
For i = 0 To 1
For j = 0 To count - 1
form = docs( j ).Form(0)
Next
Next
Erase docs
Redim docs(0)
End Function
Все правильно говорите. Все подобные вопросы треба решать с включенной головой.В данном случае - лучше потерять в скорости, чем держать открытими тысячи документов.
Во-первых, не факт, что будет быстрее, т.к. система уйдёт в глубокий своп, чтоб держать в памяти столько документов. А дисковая система, как правило, узкое место в производительности серверов.
Во-вторых, у сервера существуют ограничения на общее кол-во открытых хэнлов и пару таких агентов убьют его.
В-третьих, если даже мы оценили, что документов в списке окажется приемлемо небольшое кол-во, агент становится миной замедленного действия. Минимальное увеличение числа пользователей или интенсивности потока документов - и сервер в дауне.
Так что такой код - типичный антипаттерн. Пример того, как делать нельзя.
Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab