Lotus Script: взгляд изнутри

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
я покажу еще одно преимущество GetItemValue/ReplaceItemValue перед расширенным синтаксисом
большинство и так знает что GetItemValue/ReplaceItemValue в 10 раз быстрее чем document.Form = "test"

однако по приведенному примеру декомпиляции я не налюдаю что
rvalue_object DOCUMENT ;кладет на стек объект DOCUMENT
lvalue_document_field FORM ;кладет на стек адрес поля FORM
push_str_const {test} ;кладет на стек строковую константу
Let ;осуществляет присвоение значения переменной
в 10 раз быстрее этого

rvalue_object DOCUMENT ;кладет на стек данных объект DOCUMENT
push_lsx_routine REPLACEITEMVALUE ;кладет на стек вызовов адрес функции NotesDocument.ReplaceItemValue; класс и его функция находятся в библиотеке nlsxbe.dll
push_str_const {Form} ;кладет на стек данных строковую константу
push_str_const {test} ;кладет на стек данных строковую константу
call_routine ;вызывает функцию с вершины стека вызовов
pop ;выталкивает со стека данных неиспользуемый результат функции


Поэтому мне и нужно более расширенное обьяснение, хотя бы с позиции того же ассемблера (программировал на нем еще в детстве)
возможно вы выложили не полную декомпиляцию, как по мне в верхнем примере не хватает того "lvalue_document_field FORM ;кладет на стек адрес поля FORM" перед этой строчкой еще должно быть полно кода, как вызов функции, которая сначала проверяем является ли ".Form" свойством класса или же его обьектом/процедурой
Например
f = Doc.Authors
и
f = Doc.GetItemValues("Authors")
имеют совершенно разній результат, так как в первом случае снимается свойство дока, а во втором значение поля, которое просто одноименно его свойству


и

кстати буду благодарен если так же предоставите таблицу где "подобные" команды выполняются в 10 раз быстрее
мне это нужно чтобы закончить Анализатор - https://codeby.net/threads/lotus-analyzer-v1-6.31210/
буду искать команды типа doc.Form=val воспринимать их как ошибку и требовать заменить на call doc.Repl...("Form", val)

и еще вопросик, а декомпилятор @собачек существует? ;)
 
Y

Yakov

ToxaRat
Листинг полный.
ВМ по-разному выполняет инструкции.
Как именно выполняется инструкция lvalue_document_field, я не знаю. Видимо, ВМ приходится совершить массу разнообразных действий, чтобы выполнить эту инструкцию, и это заметно дольше, чем вызвов функции из внешней библиотеки (nlsxbe.dll) и работа этой функции.
Для декомпиляции @-формул надо бы попробовать NotesAPI функцию NSFFormulaDecompile.
 
F

fedotxxl

ToxaRat
Код:
большинство и так знает что GetItemValue/ReplaceItemValue в 10 раз быстрее чем document.Form = "test"
Доказывали, что с версии 6 (или 5) работает абсолютно одинаково по скорости
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
Не веришь, или знаешь (можешь доказать)? если да - обоснуй свою точку зрения. а если нет - не трынди, не засоряй информационное поле планеты
уважаемый у меня опыт в лотусе свыше 10 лет
если я сказал не верю, значит так и есть - это аксиома

чтобы не выглядеть быком -
11) Hardcore

- Don't use lazy field operations in LotusScript: doc.FieldName(0) and doc.FieldName=value is BAD, doc.GetItemValue "FieldName" and doc.ReplaceItemValue "FieldName",value is GOOD. The latter syntax is much faster and provides seamless data type compatibility, and also stores field names with correct case-sensitive naming in the documents.
 
T

turumbay

Кто такой Mika Heinonen? Мнение самого Жерарда на этот счет : "Not really enough difference to get excited about."


З.Ы. Нашел его блог ( ) - репостит новости других сайтов, ноль полезной инфы.
 
K

K-Fire

Вообще я некоторое время назад проводил тесты на 7.0.3 версии.

var = doc.GetItemValue()(0) быстрее var = doc.Field(0) примерно на 10-20%.

doc.ReplaceItemValue() медленнее doc.Field = "..." примерно на 30% (сейчас уже не помню точно, вроде не больше 30).


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

А учитывая что в реальных рабочих кодах GetItemValue/ReplaceItemValue занимают от силы пару процентов всего времени выполнения, вообще непонятно чего ради волноваться по этому поводу :)

ЗЫ: В 8.5. результаты аналогичные.
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
K-Fire
А учитывая что в реальных рабочих кодах GetItemValue/ReplaceItemValue занимают от силы пару процентов всего времени выполнения, вообще непонятно чего ради волноваться по этому поводу
в любой более менее автоматизированной системы есть агенты, которые по сути занимаются считыванием полей и изменением этих полей (контроль сроков, суммирование, статистика и т.д.) агентов как вы понимаете получается не мало, и то что они делают с полями тоже не мало, и это уже не пару процентов,
учитывая что большинство из них(если по грамотному) работают на сервере то и бьют они точно по серверу, и если они периодические то эти "вспышки их активности" могу приходиться на моменты когда юзеры тоже хотят что-то от сервера получить
так что не согласен ;)

var = doc.GetItemValue()(0) быстрее var = doc.Field(0) примерно на 10-20%.

doc.ReplaceItemValue() медленнее doc.Field = "..." примерно на 30% (сейчас уже не помню точно, вроде не больше 30).


Естестсвенно на результаты тестов могли влиять множество факторов, например то что документ был пустой, база тестовая и т.п., но думаю логично предположить что "работает в 10 раз быстрее" это нехилое такое преувеличение.
я гонял на милионах доках по одной записи, на реально действующих агентах, получалось именно в 10 раз
еще реальные примеры это формирование отчета в эксель - чем больше данных нужно тем в более Х раз быстрей видна разница
 
M

~Mikle

уважаемый у меня опыт в лотусе свыше 10 лет
Желаете померяться? ;) у меня сертификат CLS R5 designer датирован 16 авг 2000 года, получен был через несколько лет работы с лотусом :)
Опять же - насколько свыше? на год-другой, или на 10-15 лет? это "свыше" ничего не значит, кроме как "не менее 10 лет".

если я сказал не верю, значит так и есть - это аксиома
Я верю, что Вы не верите. Однако, кому какое дело до наших верований?
Есть эксперимент, который показывает - на 8.0.2 разница в скорости doc.replaceItemValue "field","" и doc.field="" находится в пределах погрешности измерений. Краткий синтаксис чутка быстрее. При чтении - наооборот, на 20% getItemValue шустрее.

А заявлять: "большинство и так знает" - не надо. Чтобы за большинство говорить - надо полномочия иметь :)
И тем более: " GetItemValue/ReplaceItemValue в 10 раз быстрее" - и не в 10 раз, и не оба быстрее. Хоть верь, хоть не верь - всё равно ошибаешься.

в реальных рабочих кодах GetItemValue/ReplaceItemValue занимают от силы пару процентов
Имхо, ещё и поменьше, чем пару % :)
я не за процент воюю, я против принципа подмены научного знания - верой в мракобесия :)
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
у меня сертификат CLS R5 designer датирован 16 авг 2000 года, получен был через несколько лет работы с лотусом
А к этому я еще хуже отношусь, так как реально сталкиваюсь с тем, что у людей море бумажек а на деле они их не стоят, хотя ради справедливости стоит сказать что у меня они тоже есть, но по причине того, что требовались чтобы выиграть тендер.
А так моё отношение к этому суровое - если есть бумажка, значит делать было нечего раз пошел и получил её...возможно это специфика Украины, но что-то мне подсказывает что это так везде ;)

Есть эксперимент, который показывает - на 8.0.2 разница в скорости doc.replaceItemValue "field","" и doc.field="" находится в пределах погрешности измерений.
Этот эксперимент надеюсь с сайта ИБМ хотябы?
а то какая-то нестыковка doc.replaceItemValue не даёт изменений а 20% getItemValue шустрее

а то мои эксперименты на 8.5 до сих пор утверждают про существтенную разницу

я не хочу с вами спорить, так как мне это ничего не даст

мне более интересно что расскажет Yakov , так как его раскопки имеют куда более практичную цену.
 
Y

Yakov

А Yakov ничего более не расскажет, потому что "раскопки" прекратились.
Еще раз повторю, что два подхода компилируются в разный бинарный код, и в общем случае виртуальная машина исполняет этот код по-разному. GetItemValue/ReplaceItemValue компилируется в вызов функций из внешней библиотеки (nlsxbe.dll), применение расширенного синтаксиса компилируется в однобайтовые опкоды ВМ.
 
N

nvyush

Создание объекта при объявлении переменной - это так называемый синтаксический сахар. Оба варианта компилируются в идентичный (с разницей лишь в номере строки исходного кода) байт-код.
Для эксперимента создал две ЛС библиотеки.
В первой:
Код:
Sub Initialize
Dim s As New NotesSession
Dim db As NotesDatabase
Set db = s.CurrentDatabase
Dim doc As New NotesDocument(db)
Dim rti As New NotesRichTextItem(doc, "Body")
End Sub
Во второй:
Код:
Sub Initialize
Dim s As New NotesSession
Dim db As NotesDatabase
Set db = s.CurrentDatabase
Dim doc As NotesDocument
Set doc = db.CreateDocument
Dim rti As NotesRichTextItem 'Dim rti As New NotesRichTextItem(doc, "Body")
Set rti = doc.CreateRichTextItem("Body")	
End Sub
Размер поля $ScriptLib_O для первой 2071 bytes, для второй — 2247 ([strike]2264[/strike]) bytes. А Вы говорите — сахар...
P.S. Дизайнер 8.0.1.

Правки были вызваны опечаткой в строке с комментарием второго примера. Спасибо OKEN за внимательность.
 
Y

Yakov

nvy, ну так вы во втором случае сделайте Set doc = New NotesDocument(db). Почти 200 байт отъело описание метода NotesDatabase.CreateDocument().
 
N

nvyush

nvy, ну так вы во втором случае сделайте Set doc = New NotesDocument(db). Почти 200 байт отъело описание метода NotesDatabase.CreateDocument().
Создал третью либу с кодом:
Код:
Sub Initialize
Dim s As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim rti As NotesRichTextItem
Set db = s.CurrentDatabase
Set doc = New NotesDocument(db)
Set rti = New NotesRichTextItem(doc, "Body")
End Sub
Размер поля $ScriptLib_O как и в первом примере — 2071 bytes. Действительно, код
Код:
Dim doc As New NotesDocument(db)
и код
Код:
Dim doc As NotesDocument
Set doc = New NotesDocument(db)
компилируются в эквивалентный байт-код. Увеличение размера байт-кода во втором примере поста 89 объясняется видимо тем, что конструкторы классов NotesDocument и NotesRichTextItem вызываются не непосредственно, а методами CreateDocument и CreateRichTextItem соответственно.
Однако использование раздельного описания объектной переменной и её инициализации всё равно увеличивает размер библиотеки за счёт исходного кода (для примеров 1 и 3 размер библиотеки 4320 и 4394 байтов соответственно). Так что если при исполнении библиотека загружается целиком, а не только исполняемый код, то быстродействие второго варианта всё равно ниже за счёт передачи большего объёма информации по сети. Что скажут по этому поводу знатоки глубин Лотуса?

почему не:
Код:
 Dim rti As NotesRichTextItem
Set rti = doc.CreateRichTextItem("Body")
Опечатка/описка. Исправил в посте.
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
Yakov
а я обычно вот так вич юзаю
Код:
With doc
call .replaseItemValue("itemName", itemValue)
End With
это тоже не верно?

и что-то я не понял
это
Код:
Dim doc As NotesDocument
Set doc = New NotesDocument(db)
лучше чем это?
Код:
Dim doc As NotesDocument
Set doc = db.CreateDocument

Если нужно запретить витч то я не особо и против, так как не любитель его юзать, но мне витч всегда казался предкомпиляторным кодом, который перед компиляцией всегда правится с добавлением того обьекта

лично я всегда оперируюсь на компилятор 6.5.6 хотя бы из причины того, что у меня некоторые заказчики с 6-ке не слезут никогда ;)
 
N

nvyush

и что-то я не понял
это
Код:
Dim doc As NotesDocument
Set doc = New NotesDocument(db)
лучше чем это?
Код:
Dim doc As NotesDocument
Set doc = db.CreateDocument
Мои эксперименты показывают, что байт-код в первом случае получается короче. Аналогичная картина для New NotesRichTextItem против doc.CreateRichTextItem. Так что использование New выгоднее. Правда он в COM не поддерживается, но для ЛС это не принципиально.
 
Мы в соцсетях:

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