Форум компании Кронос-Информ
http://www.cronos.ru/cgi-bin/YaBB2/YaBB.cgi
Конференции для пользователей >> CronosPRO: Lua >> Заполнение списка и словарные поля
http://www.cronos.ru/cgi-bin/YaBB2/YaBB.cgi?num=1642155596

Сообщение написано Юзер99335588 в 14.01.2022 :: 14:19:56

Заголовок: Заполнение списка и словарные поля
Создано Юзер99335588 в 14.01.2022 :: 14:19:56
Здравствуйте!

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

Условно есть таблица и в ней есть, среди прочего, три поля: тест, словарь, словарь (оба словаря множественные)

Запросом по образцу получаю набор значений RecordSet
Далее в цикле прохожу по всем значениям набора, так же мне надо значения словаря преобразовать в одну строку
пример: 1 - Бег
             2 - Отжимание
             3 - Велосипед
делаем из этого строку: Бег; Отжимание; Велосипед


Цитировать:
for record in RS.Resords do
   local str1=record:GetValue(2)
   local str2=FnConv(record:GetValue(6, 0, true, 1))
   local str3=FnConv(record:GetValue(12, 0, true, 1))

   Me.list1:Add(str1.."  "..str2.."  "..str3)
end


и есть функция, что превращает таблицу в строку и добавляет некое число пробелов в эту строку, чтобы в списке строка выглядела как Таблица с колонками (на форму есть хороший пример как программно сформировать такую таблицу). Я эти пробелы добавляю в цикле, может быть в этом и происходит задержка?
А как можно в строку сразу добавить нужно число пробелов? Мне это нужно, чтобы форматирование строки было правильным, моя этого даже приходится использовать шрифт моноширный


Цитировать:
func FnConv(tbl)
   local str=""
   for _, item in pairs(tbl) do
     str=str..item..";"
   end
   if string.len(str)<40 then
      local div=40-string.len(str)
      for i=1, div do
          str=str.." "
      end
   end
end

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 14.01.2022 :: 16:26:29
а вот есть возможность в список добавлять не по строчно, а сразу массивом?

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 14.01.2022 :: 16:53:39
[code]for record in RS.Resords do
   local str1=record:GetValue(2):cr(40)
   local str2=table.concat(rec:GetValue(6,0),"; "):cr(40)
   local str3=table.concat(rec:GetValue(12,0),"; "):cr(40)

   Me.list1:Add(str1.."  "..str2.."  "..str3)
end[/code]

Заполнение массивом возможно в элементе ComboBox. Про ListBox неизвестно.
Для создания таблиц в 7 версии появился элемент  TableControl и не надо ничего изобретать с ListBox.

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 14.01.2022 :: 16:59:00
у меня, к сожалению, версия 6.4.300.....
и создание списка из допустим 100....300....600 записей занимает десятки секунд

спасибо за concat, вот что значит опыт  ;)

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 14.01.2022 :: 17:33:27
До 400 строк список должен заполняться менее чем за 1 секунду. Возможно у Вас очень большие текстовые значения, которые надо ограничивать. Например, до 40 знаков. val:sub(1,40)

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 14.01.2022 :: 17:36:10
Попробуйте сделать в два этапа. В первом формировать таблицу значений в переборе записей. Во втором сделать вывод таблицы в список. Посмотрите время формирования каждого этапа.

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 14.01.2022 :: 17:42:39
огромное спасибо!

а можно пример кода, типа профайлера, чтобы засечь время выполнения блока кода?

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 14.01.2022 :: 17:47:20

Zuluss записан в 14.01.2022 :: 17:33:27:
До 400 строк список должен заполняться менее чем за 1 секунду. Возможно у Вас очень большие текстовые значения, которые надо ограничивать. Например, до 40 знаков. val:sub(1,40)


у меня в списке строка в списке по итогу должна быть  ~110 символов

и исходная строка практически попадает в нужные рамки, а словарные поля тоже не большие(даже если все значения сложить в одну строку)

список из пары сотен записей RecordSet`a заполняется более 15 секунд и это напрягает
Запрос практически мгновенно, а вывод на форму многие секунды

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 14.01.2022 :: 17:54:44

Zuluss записан в 14.01.2022 :: 17:36:10:
Попробуйте сделать в два этапа. В первом формировать таблицу значений в переборе записей. Во втором сделать вывод таблицы в список. Посмотрите время формирования каждого этапа.



Цитировать:
Попробуйте сделать в два этапа. В первом формировать таблицу значений в переборе записей. Во втором сделать вывод таблицы в список. Посмотрите время формирования каждого этапа.


и ещё раз повторюсь, что опыт это бесценная вещь !!!! :D

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

Спасибо!

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 14.01.2022 :: 18:05:12
[code]
local t_1=GetTicks()
do
--block 1
end
local  t_2=GetTicks()
do
--block 2
end
loca t_3=GetTicks()
do
--block 3
end
loca t_4=GetTicks()
MsgBox(t2-t1)
MsgBox(t3-t2)
MsgBox(t4-t3)

[/code]

Заголовок: Re: Заполнение списка и словарные поля
Создано Sinilga в 15.01.2022 :: 11:11:12
Попробуйте так:
[code]
for record in RS.Resords do
   local str1=record:GetValue(2)
   local str2=record:GetValue(6, 0, true, 1)
   local str3=record:GetValue(12, 0, true, 1)
   local item = ("%s %40s %40s"):format(str1,table.concat(str2,";"),table.concat(str3,";") )
   Me.list1:Add(item)
end
[/code]


Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 17.01.2022 :: 10:44:53

Zuluss записан в 14.01.2022 :: 18:05:12:
[code]
local t_1=GetTicks()
........
[/code]


я попробовал и получаются такие результаты (230 записей в ответе):
при выполнении запроса (запуск клиента на сервере) заполнение таблицы в цикле for->do->end занимает 1.919 тактов
при выполнение того же запроса на машине пользователя по сети заполнение таблицы занимает 74.023 такта

у пользователей Кронос запускается через ярлык, в котором просто указан путь до exe файла Cronos.exe папки с установленным дистрибутивом на сервере. Сервер 2008

Что я делаю не так? Почему такая разница во времени исполнения кода?

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 17.01.2022 :: 16:43:35
Вопросы замедления работы при сетевых подключениях неоднократно обсуждались на форуме.
Например,тут и тут. Решения по нормализации скорости никоим образом не связаны с самой программой, а связаны с настройкой работы сервера, антивирусника, структуры банка, системного журнала и др.

GetTicks() возвращает значения в миллисекундах.

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 17.01.2022 :: 16:59:55
сам запрос у меня выполняется быстро, а вот формирование списка и вывод данных на форму отнимает основное время

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 17.01.2022 :: 17:17:42
у меня строка списка состоит из трех подстрок, две из которых словарное/множественное поле

так вот если брать только строку без словарей ,то скорость выполнения приемлемая
но при вычислении словаря сразу проседает скорость вывода формы на ПК пользователя по сети

Мне кажется, что происходит чтение словаря при формировании каждой строки, а можно ли словарь загрузить в память и просто, как в списке находить значение и подставлять его (словарь при этом одни раз в начале будет загружен) ?

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 17.01.2022 :: 17:36:55
Для начала проведите ревизию и оптимизацию основного банка и словарного. Затем в этих банках постройте индексы по всем индексным полям. Особенно, по полям код и понятие в словарях. Затем снова попробуйте на скорость.

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 17.01.2022 :: 18:15:24
спасибо!

скорость вывода возросла

А можно у словарных полей получать код, но без обращения к самой словарной базе? Я бы программно заполнял поле текстом, создав таблицу в памяти, а не выполнять чтение словаря для каждого значения

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 17.01.2022 :: 18:38:52
Можно и так сделать.
Словарь это точно такой же банк данных, как и основной. Работать с ним можно точно так же. Можно загрузить в память все словари, если они не огромных размеров. Только сомнительно, что это даст большой выигрыш. Дело в том, что обращение к словарю и получение понятия это обычный запрос, который выполняется очень быстро. Можете проверить.

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 17.01.2022 :: 18:39:27
вот у Record есть два метода: GetValuesCount и GetFieldsValuesCount

а можно как-то получить сами эти значения, без декодирования значений?

словари смешные, под сотню значений

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 17.01.2022 :: 18:57:05
Ну, так Вы эти значения и получаете.
GetValue(6, 0, true, 1) -- это декодированные.
GetValue(6, 0, false) -- это не декодированные.

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 18.01.2022 :: 17:00:19
на данный момент пришел к такому решению:

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

Цитировать:
Form_Load(form)
     base = CroApp:GetBank():GetBase(1)
     voc = CroApp:GetBank():GetVocabulary()
     voc_1 = voc:GetBase(1):GetRecordSet()
     voc_2 = voc:GetBase(2):GetRecordSet()
end


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

Цитировать:
tbl = {}
for record in voc.Records do
   code = record:GetValue(1)
   concept = record:GetValue(2)
   tbl[code]=concept
end
return tbl


далее выполняю запрос по образцу и результат запроса + словари передаю в форму отображения результатов

Цитировать:
formArg = {}
formArg.list = records
formArg.voc_1 = tbl_voc_1
formArg.voc_2 = tbl_voc_2
CroApp.GetBank(): OpenForm(2,0,Me,formArg)


в форме вывода результата  создаю этот сам список

Цитировать:
ArgRec = Arg.list
ArgVoc_1 = Arg.voc_1
ArgVoc_2 = Arg.voc_2

for record in ArgRec.Records do
    local str1 = FncReturnStr(record:GetValue(1,0,false), ArgVoc_1, 40)
    local str2 = FncReturnStr(record:GetValue(2,0,false), ArgVoc_2, 40)
    local str3 = record:GetValue(3):lr(40)
    Me.list1:Add(str1.." "..str2.." "..str3
end

FncReturnStr(tbl, voc, num)
   local str=""
   for _, I in pairs(tbl) do
      str = str..voc[I].."; "
   end
   return string.lr(str, num)
end


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

Большое спасибо за подсказки.

Как я понимаю если делать отображение результатов по стандартной форме, то замедления нет. Авторы системы используют какие-то свои механизмы создания таблицы просмотра со словарными полями (возможно они используют динамическую загрузку данных только для тех строк, что в данный момент видны на экране), а вот если использовать самописные формы вывода результатов - тут нужно искать решения и что-то придумывать (это актуально для версии 6, для версии 7 вроде как сделали нужный контрол)

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 18.01.2022 :: 17:43:20

Цитировать:
38.320
Это в секундах и 10-ти тысячных долях или в миллисекундах?
Если 38 секунд для 14 к записей, то это много. Такие вопросы быстродействия здесь на форуме поднимались. Были найдены более оптимальные решения.

Цитировать:
список на 14к записей
- это записей банка с декодированными словарными полями или список значений словаря?

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 18.01.2022 :: 18:06:41
да, это в секундах
Я читал про "производительность" и по вашим ссылка в теме и по общему поиску, но там решения были на уровне "железной" части
"Программных" способов речения проблемы я не увидел, кроме настройки ОС

14к это ответ на запрос (число записей), в котором 10 полей и несколько из них словарных, которые я декодирую программно, а не средствами Кронос ( GetValue(2, 0, true, 1)  )

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 18.01.2022 :: 18:23:04

Цитировать:
...
Я читал про "производительность" и по вашим ссылка в теме и по общему поиску, но там решения были на уровне "железной" части
"Программных" способов речения проблемы я не увидел, кроме настройки ОС...

Это совершенно разные вещи. Одно дело ускорение работы системы (Cronos.exe)
и другое оптимизация скорости работы программного кода форм.
Вот одно из последних обсуждений оптимизации скорости.
Провел испытания заполнения списка всем содержанием базы КЛАДР (перебором RecordSet) более 220 тысяч строк. Результат - 5 секунд. (Локальная машина - ноутбук 10 летней давности core i3, win7 64, 8 Гб)

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 18.01.2022 :: 18:39:51

Zuluss записан в 18.01.2022 :: 18:23:04:
[quote]...
Локальная машина - ноутбук 10 летней давности core i3, win7 64, 8 Гб


здесь ключевое слово - локальная машина

я пока формы делал даже не задумывался о скорости работы, всё было просто на "Ура"
но как только свою форму запустил на машине пользователя, то был не приятно удивлён временем выполнения

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 18.01.2022 :: 18:50:29

Цитировать:
как только свою форму запустил на машине пользователя, то был не приятно удивлён временем выполнения

Это не проблемы формы или Cronos-а. Это проблемы сети, и даже не сервера. Это может быть и одноранговая сеть вообще без сервера.

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 18.01.2022 :: 19:02:59
чуть отойдя от основной темы:

вариантов запуска на ПК пользователей два

- ссылка ярлыка на "расшаренную" папку с установленным Кронос на условном сервере
- запуск терминалов удаленного рабочего стола на ПК пользователей и в этом терминале запуск Кронос

правильно я понимаю?

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 18.01.2022 :: 21:16:07
По крайней мере это самые распространенные варианты и активно используются. Ничто не мешает использовать их одновременно. Заодно можно сравнить скорость работы одинаковых задач.

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 19.01.2022 :: 10:08:33
Спасибо большое!

Сдаётся мне, из того, что я на форуме читал, по скорости будет лучшим вариант с удалённым рабочим столом. Потому что не будет передачи массивов по сети, только данные необходимые для отображения самого рабочего стола.

Если получится, я попробую создать сессию и проверить этот вариант

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 19.01.2022 :: 11:58:11

Цитировать:
... по скорости будет лучшим вариант с удалённым рабочим столом. Потому что не будет передачи массивов по сети, только данные необходимые для отображения самого рабочего стола...

Это может быть обманчивым мнением. Например, для передачи картинки одного кадра рабочего стола со средним разрешением (1280х1024х24 бит) требуется передать около 4 Мб. Для плавности отображения требуется частота обновления не менее 16 кадров в секунду. Т.е. суммарный объем для одного рабочего стола 64 мегабайта в секунду. Т.о. пропускная способность сети должна быть не менее 512 мбит/сек даже без учета передачи служебной информации. И это только для одного рабочего стола (УРС), если я не ошибся (запутался) где то в расчетах. Эти расчеты не учитывают адаптивные возможности УРС, т.е. отправку данных только при изменениях на экране, и сжатия данных. Это позволяет значительно снизить требования к пропускной способности. Тем не менее перемещение мыши на 1 пиксель уже является необходимостью отправки обновленного экрана.
Можно сделать вывод о том, что передача массива данных из банка данных к клиенту требует меньше сетевых ресурсов, чем при передаче экрана УРС.
Провел эксперимент с заполнением списка. В моих условиях получилось порядка 50-60 тысяч строк в секунду со средним объемом строки 64 байта. Суммарный объем примерно 3.2 Мб. Это сравнимо с передачей только одного экрана УРС. В наихудшем случае для отображения списка потребуется передать  50-60 тысяч экранов, в реальности происходит эффект зависания и потом предъявляется заполненный список.
Вот такая математика получилась. Если где то неверно что то трактую приму все замечания с благодарностью.

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 19.01.2022 :: 20:58:30
Я попытался программно создать похожий банк, сделал в нём 32к записей
Моя форма внутри архива
Посмотрите пожалуйста, есть разница по времени исполнения если словарь декодировать или из таблицы программно вычислять

Спасибо.

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

https://disk.yandex.ru/d/c80D6u7AZlLW5Q

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 20.01.2022 :: 00:25:24
Действительно. Получение декодированных словарных значений почти в 10 раз увеличивает время формирования списка. Формирование словарей в памяти в виде таблиц и декодирование из них позволяет значительно увеличить скорость работы.

Code (]function GetVocs()-- формирование таблиц словарей в глобальную таблицу Vocs. Запускать в событии Load
     Vocs={{},{}}
     local rs=CroApp:GetBank():GetVocabulary():GetBase(1).RecordSet
     for record in rs.Records do
           Vocs[1):

[record:GetValue(1)]=record:GetValue(2)
     end
     rs=CroApp:GetBank():GetVocabulary():GetBase(2).RecordSet
     for record in rs.Records do
           Vocs[2][record:GetValue(1)]=record:GetValue(2)
     end
end

function DecodeVals(t,numvoc)-- получение декодированных значений по номеру словаря numvoc из таблицы t и выдача в виде строки
     local out={}
     for k,v in ipairs(t) do
           table.insert(out,Vocs[numvoc][v])
     end
     return table.concat(out,"; ")
end

-- пример использования
--local v=record:GetValue(6,0,false)
--local str2=DecodeVals(v,1)

Заголовок: Re: Заполнение списка и словарные поля
Создано Юзер99335588 в 21.01.2022 :: 10:28:03
Спасибо большое!

Если работать со стандартным (табличная форма Кроноса) выводом информации проблем нет. 90+М записей в виртуальном ПК на не свежей ЭВМ работает всё шикарно, без тормозов. А вот если надо что-то "своё", то появляются нюансы

А вот такой ещё вопрос: можно ли как-то создавать и запускать сценарий Lua в Кроносе без создания форм? Или они только в формах существуют?

Заголовок: Re: Заполнение списка и словарные поля
Создано Zuluss в 21.01.2022 :: 10:55:22

Цитировать:
...можно ли как-то создавать и запускать сценарий Lua в Кроносе без создания форм? Или они только в формах существуют?


скрипты управляющих и входных форм (обычно именуются просто скриптами форм); 
скрипты банка;
системные скрипты.
Описаны в справке по Cronos и CroLua.
Ничто не мешает запускать форму и скрипт и сделать ее невидимой.


Форум компании Кронос-Информ » Powered by YaBB 2.5.2!
YaBB © 2000-2009. Все права защищены.

Localization by mySOPROMAT.ru