Используется bpm'online sales 7.7 после перехода с Terrasoft, т.е. все данные были перенесены (порядка 6 млн. активностей). По результату Terrasoft отрабатывает быстрее чем bpm'online. При запуске сайта локально на сервере отрабатывает терпимо, при работе на пользовательских машинах иногда данные вообще не отображаются.

Может кто-то может поделится наработками в вопросе увеличения быстродействия bpm'online on-site: где/как искать проблему, как/что оптимизировать.

Нравится

3 комментария

Здравствуйте.
Не совсем корректно сравнивать быстродействие BPM'online и Terrasoft 3.x. Эти систему имеют абсолютно разную архитектуру. Terrasoft 3.x - это классическая 2-звенная (клиент-сервер) система. BPM'online - 3-звенная (клиент-сервер базы данных-сервер приложения). Если время отклика системы значительно отличается на сервере и на клиентской машине, тогда стоит обратить внимание на сетевую составляющую (стабильность, ширина канала, особенно если это Wi-Fi), также нужно обеспечить достаточные ресурсы клиентской машины (часть кода выполняется, именно, на пользовательском ПК). Также рекомендую в connectionstrings.config в строке подключения к Redis-серверу не использовать в качестве адреса localhost или 127.0.0.1 (указать сетевое имя или реальный IP-адрес). В противном случае игнорируются параметры, отвечающие за многопоточность подключения к Redis. Это параметры maxReadPoolSize=; maxWritePoolSize= (находятся в том же файле в той же строке). По умолчанию равны – 25. Желательно устанавливать по количеству пользователей *10.

Олег, а вы в браузере посмотрите сколько запросов идет и как долго они выполняются. Таким образом сможете выявить где тормозит и падает.
Например, в версии 7.2 по умолчанию стоит таймаут в 30 секунд на запрос. В результате любые запросы более менее тяжелые могут отвалиться, и при этом останется висеть лоадер, либо просто ничего не произойдет. Самый простой вариант, руками поменять таймаут на больший. И как показывает практика, больше времени уходит на обработку уже на серверной стороне.

Александр подскажите где эта настройка устанавливается ?

Показать все комментарии

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

Сейчас используется sales commerce 7.5.0.1544 on-demand.

Контрагентов около 100
Лидов около 500
Контактов тоже около 600
То есть немного.

Реально очень часть подолгу загружаются реестры.
Понятно еще, например, когда это в первые раз после обновлений конфигурации, перекешируется наверно вот это всё. Но потом-то?
Причем часто очень неожиданно, например ни с того ни с сего может очень долго загружаться реестр справочников.

Может быть есть рекомендации и best practice по использованию конкретных браузеров, их настроек, определенных системных настроек?

Нравится

4 комментария

Я бы начал не с браузеров, а со скорости канала и его качества. Как вариант посмотреть как пинг идет от вас до серверов on-demand где узкие места.
Потом смотрел бы на процесс открытия страницы с точки зрения потребления ресурсов браузером на конкретной клиентской машине - сколько памяти доступно, сколько "ест", сколько ресурсов процессора доступно и используется в процессе.

Пинг и канал нареканий не вызывают, это я смотрел в первую очередь.
Ответ от 195.189.123.118: число байт=32 время=2мс TTL=117
Ответ от 195.189.123.118: число байт=32 время=2мс TTL=117
Ответ от 195.189.123.118: число байт=32 время=2мс TTL=117
Ответ от 195.189.123.118: число байт=32 время=2мс TTL=117

Добрый вечер!

Для браузера Google Chrome для увеличения быстродействия можно отключить аппаратную часть. Инструкция следующая:
1) Откройте страницу настроек:

2) Нажмите ссылку отображения расширенных настроек:

3) Отключите флаг "Use hardware acceleration when available" в блоке "System":

Так как у вас on-demand дам радикальный совет - озадачьте производительностью не себя, а команду поддержки on-demand, если проблема на их стороне они ее будут решать, а нет - так в процессе выяснения укажут на "узкие" места в канале, браузере :) как я понимаю, именно в этом смысл облака и платной поддержки

Показать все комментарии

Вопрос быстродействия зависит от нескольких факторов – быстродействие ресурса, локальной сети, интернет-соединения и т.д. Заявленное время открытия карточки для версии 5.3 – 2-3 секунды. В 5.2 это немного медленнее, в 5.4 – немного быстрее.

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

Вам понадобится:
Google Chrome с установленным компонентом Инструмент разработчика (как правило, установлен по умолчанию).

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

1. Откройте необходимую страницу (например, страницу карточки контакт) и дождитесь ее полной загрузки. После этого активируйте инструменты разработчика:

devtools1

2. Откройте в инструментах разработчика консоль:

devtools2
3. Вставьте в консоль скрипт (ниже) и нажмите Enter.

 

(function CheckPerformance() {
        if (typeof PageContainer_HtmlMainPage === 'object') {
               var mainPageWindow = PageContainer_HtmlMainPage.getWin();
        }
        var targetWindow = mainPageWindow || window;
        var manager = targetWindow.Terrasoft.PerformanceCounterManager;
        manager.getProfileInfo();
        var performance = targetWindow.performance || targetWindow.mozPerformance||
               targetWindow.msPerformance || targetWindow.webkitPerformance;
        var timing = performance.timing;
        var navigationStart = timing['navigationStart'];
        var responseStart = timing['responseStart'];
        var responseEnd = timing['responseEnd'];
        var loadEventEnd = timing['loadEventEnd'];
        var onReadyEnd = manager.getCounter('onReady').finishTime;
        var networkTime = timing['responseEnd'] - timing['responseStart'];
        var serverTime = responseStart - navigationStart;
        var parseJsTime = loadEventEnd - responseEnd;
        var execJsTime = onReadyEnd - loadEventEnd;
        var fullTime = serverTime + networkTime + parseJsTime + execJsTime;
        var output = 'Передача запроса  + Обработка на сервере: ' + serverTime + '\nПрием ответа: ' + networkTime + '\nПарсинг JavaScript: ' + parseJsTime +
               '\nВыполнение JavaScript:' + execJsTime + '\nОбщее время: ' + fullTime;
        return output;
})();

 

4. После того, как скрипт выполнится, в консоли внизу появится результат выполнения скрипта:

devtools3

5. Кроме того, следует произвести тестирование скорости обращения к серверу по следующей ссылке:
http://speed.bpmonline.com/

По результатам проверки можно определить, на каком этапе теряется производительность, и устранить узкие места.

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

Это справедливо для версий 5.3 и новее. Для версии 5.2 IIS автоматически не перезапускается, и при интенсивной разработке по завершении доработок в конфигурации имеет смысл перезапустить его вручную.

Нравится

Поделиться

7 комментариев

Интересный показометр. Как бы для "тройки" такое сделать...

А что могут означать отрицательные значения в результате:

"Обработка на сервере: 644
Сеть: 14
Парсинг JavaScript: 243
Выполнение JavaScript:-5437
Общее время: -4536"

Павел, уточните, пожалуйста, какая у Вас версия и какой браузер используется?

Очень похоже, что компонент таймера загрузки (targetWindow.Terrasoft.PerformanceCounterManager), к которому мы обращаемся в скрипте, не существует либо недоступен.

"paveles" написал:

А что могут означать отрицательные значения в результате:

"Обработка на сервере: 644

Сеть: 14

Парсинг JavaScript: 243

Выполнение JavaScript:-5437

Общее время: -4536"


Такое иногда бывает.
Если в результатах выполнения скрипта существуют отрицательные значение, то эти данные не корректны. В таком случае необходимо обновить страницу (F5) и выполнить скрипт повторно.

Также, есть замечательный инструмент, который дает более подробную картину происходящего - это Fiddler:
1. Установить Fiddler http://www.getfiddler.com/dl/Fiddler2Setup.exe
2. Запустить.
3. Включить опцию дешифровки https запроса.
Меню Tools->Fiddler Options.

В появившемся окне выбрать вкладку HTTPS и установить флажок “Decrypt HTTPS traffic”, после чего нажать кнопку “OK”. На все вопросы отвечать “Yes”
4. Перед тем как профайлить нужные действия, необходимо очистить список сессий в Fiddler.

5. Выполнить действия, которые необходимо запрофайлить. Сценарий ниже.

6. Сохранить сессии в файл. Меню File->Save->All Sessions.

выдает ошибку 

TypeError: Cannot read property 'getProfileInfo' of undefined

 

Это статья относится к 5.Х, а в нынешней 7.Х движок пользовательского интерфейса полностью другой. Но совет Арсения по поводу Fiddler стал ещё актуальнее, поскольку много операций теперь вынесено на клиентскую сторону и обмен браузера данными с сервером стал доступнее для анализа.

Показать все комментарии

Доброго времени суток, посетители Terrasoft Community!

Сегодня хочу с Вами поделиться информацией о том, как в случае обнаружения проблем с быстродействием BPMonline On-Demand выявить источник проблемы.

Так как физически сервера BPMonline хостятся в датацентре, то серверное оборудование в этом случае полностью удовлетворяет рекомендуемым требованиям к системе. Поэтому чаще всего в подобных случаях проблема заключается либо в пользовательских ПК, либо же в каналах связи пользователь-датацентр.

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

Как мы можем видеть, требования довольно невысоки и практически любой современный ПК с лихвой покрывает эти требования. Более примечательным является требования к каналу связи, а именно то, что для комфортной работы в BPMonline ширина канала должна составлять 512 Кб/сек на пользователя системы. Таким образом, если одновременно с BPMonline работает 5 пользователей из одной локальной сети, ширина канала интернет_шлюз_этой_ сети - сервер должна быть 512*5=2,5 Мб/сек.

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

В первую очередь рекомендую Вам воспользоваться сервисом тестирования скорости, который доступен на нашем датацентре. Для этого перейдите по ссылке:
SpeedTest

На открывшейся странице нажмите на кнопку [Begin test]. В результате Вы получите результат тестирования скорости непосредственно на шлюз датацентра:
SpeedTest

Затем попробуйте выполнить трассировку к этому шлюзу. Для этого в интерпретаторе Windows выполните следующие команду:
tracert your_web_site - где your_web_site – URL Вашей конфигурации.
В результате Вы сможете просмотреть время отклика от каждого из шлюзов, которые проходит пакет до попадения на гейт BPMonline.
Tracert

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

Также в том случае, если технических специалистов, которые смогут получить аналитику согласно этой информации, у Вас в штате нет, то результаты выполнения этих двух простых действий Вы можете направлять в департамент технической поддержки компании Terrasoft по email support@terrasoft.ru

Надеюсь, что эта информация будет полезна!:wink:
_______________________
Симоненко Владислав
и.о. Руководителя CSM
Группа компаний Terrasoft

Нравится

11 комментариев

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

Да, но зачастую это дает понять, в каком направлении искать проблему.
Например, у меня на практике был случай, когда при трассировке у клиента на первом же шаге время было более 100 мс. Оказалось, что у клиента были проблемы с роутером, который и вызывал проблемы с быстродействием не только приложения, но и работы в сети Internet в целом, хотя ширина канала вроде-бы удовлетворяла требованиям. Так что как первый способ поиска проблемы я думаю, что все-таки аналитику из описанных шагов получить получится.

Со временем я буду дополнять эту тему более детальной информацией.

Уважаемые коллеги,

Как новый пользователь BPMOnline CRM, хочу добавить комментарий (подчеркиваю, со стороны Пользователя). Первое впечатление - несколько настораживает (если не сказать удручает), замедление со временем скорости открытия новых окон, например, при первичном наполнении справочников. Простая задача - заведение списка необходимых нам стран и городов в этих странах происходила следующим образом:
- Создаю страну
- Создаю город №1 в стране
....
- Создаю город №15 в стране
- Выхожу из системы (т.к. открытие окна занимает около 5 секунд, по сравнению с мгновенным откликом в самом начале)
- Закрываю браузер (т.к. он "съел" около 1Gb памяти)
- Открываю браузер, продолжаю вводить данные и так далее.

Пробовали использовать несколько браузеров (IE, FireFox, Chrome), результат везде один и тот же.
Сейчас провожу простой эксперимент - последовательно открываю и закрываю карточки клиентов (просто на чтение, никаких изменений не вношу). Через 15 карточек браузер (Chrome) использует 218Mb памяти (до открытия первой карточки - 60Mb), скорость открытия карточек замедляется, что видно невооруженным взглядом.
На мой взгляд - это ненормально.

Инсталляция Onsite, Версия 5.2.0.359, SQL2008R2, Сервера приложения и баз данных - новые машины с W2008R2 со всеми апдейтами, с сетью проблем нет (прочие корпоративные приложения работают без проблем с производительностью).

Константин, Ваш запрос переведен в департамент разработки и тестирования.
По результату работ мы с Вами свяжемся, сообщим о решении.

А если при соединении с локально поднятым (время отклика <1мс) тормоза? Куда копать?
Симптомы - на клиенте Google Chrome, после входа и перехода на раздел Контрагенты первый подъем карточки Контрагента при нажатии кнопки Добавить 20 секунд.

Александр, время отклика в данном случае не влияет на работу приложения. Т.к. пакеты ICMP низкоуровневые и они не позволяют объективно оценить загрузку приложения на сревере.

Большая продолжительность открытия карточки при первом ее запуске, связан с построением кешируемых объектов в самой системе. Это время, в частности, может зависеть от производительности серевра и выделенной физической памяти, для сервера приложения.

А замечается ли разница при тех же действиях, производимых на самом сервере?

Константин, к сожалению со стороны сервера приложенния мы не можем непосредственно повлиять на выделение и освобождение памяти браузером. В Chrome, например, все открываемые окна (и ссылки тоже) используют контекст родительской вкладки, причем ресурсы полностью не высвобождаются вплоть до ее закрытия. Это не связано с BPMonline и происходит на любых сайтах, когда одна страница постоянно остается открытой и с нее часто открываются новые окна.
В результате, при длительной работе с BPMonline выделение памяти в Chrome может достигать значительных размеров. С Firefox таких проблем не обнаружено, но при открытии окон некоторые плагины, в частности - Firebug, тоже могут вызывать утечки памяти и существенно увеличивать ее потребление.
Как правило, 218Мб выделенной браузером памяти (при наличии ее порядка 2Гб) не должно влиять на производительность приложения. Попробуйте, пожалуйста, сделать дамп сессий в Fiddler и выслать нам результаты.

Красткая инструкция по настройке Fiddler прикреплена.

"Фильковский Павел" написал:

Александр, время отклика в данном случае не влияет на работу приложения. Т.к. пакеты ICMP низкоуровневые и они не позволяют объективно оценить загрузку приложения на сревере.

Большая продолжительность открытия карточки при первом ее запуске, связан с построением кешируемых объектов в самой системе. Это время, в частности, может зависеть от производительности серевра и выделенной физической памяти, для сервера приложения.

А замечается ли разница при тех же действиях, производимых на самом сервере?

С уважением, Фильковский Павел

Специалист службы поддержки

Группа компаний Terrasoft


Павел, спасибо за ответ! Разрешение этой проблемы перевели на данный момент полностью на нашего специалиста техподдержки, поэтому свой вопрос снимаю.

При переходе на http://speed.bpmonline.com/, перенаправляет на главную страницу http://www.bpmonline.com/

Иван, данным вопросом сейчас занимаются администраторы площадок on-demand.

Сайт восстановлен!

Показать все комментарии

Некоторые собранные мысли, идеи по поводу быстродействия системы Terrasoft CRM

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

Лабьяк Олег Игоревич пишет:
На быстродействие системы может влиять довольно много параметров. В первую очередь сервер и клиентские места должны удовлетворять аппаратным и программным требованиям для использования программы Terrasoft. Они описаны в документе "Руководство администратора", который поставляется вместе с программой. Также быстродействие зависит от размера базы данных и количества активных подключений к серверу БД.

Проверьте также, включено ли в Вашей базе данных кеширование (для этого необходимо установить значение 1 в колонке UseCache таблицы tbl_DatabaseInfo). Если включена данная опция, память под конкретный экземпляр объекта выделяется только один раз при его создании. При последующих обращениях эти объекты берутся из кеша.

Ещё одна возможная причина - реализация некоторого функционала при открытии раздела. Проверьте профайлером, не выполняются ли в это время запросы, напрямую не связанные с разделом, таблицей tbl_Service и напоминаниями. Очень может нагружать систему использование вызова Services.GetNewItemByUSI(...), особенно в циклах (в результате экземпляр объекта не подтягивается из кеша, а каждый раз создаётся новый экземпляр). Необходимо по возможности этого избегать, используя для получения экземпляров объекта функцию GetSingleItemByCode.

Михайлюк Юра пишет:
Від себе можу додати, я помітив, що продуктивність залежить від кількості активних (відкритих датасетів). Особливо коли вони знаходяться в режимі редагування. Террасофт рекомендує в деяких випадках вимикати реагування на події і після редагування записів вмикати(Dataset.DisableEvents()/Dataset.EnableEvents()).
Мені в одній із карточок реально вдалося підвищити швидкість відображення разів в 10 лише відключивши у відкритих датасетах (з яких дані лише беруться) режим редагування.

Ще один фактор який мені порадили, по мінімуму прив'язувати таблиці до системи перевірки прав доступу. Можете перевірити на свойому клієнті під Адміністратором (мабуть блок "Адміністрування по записам" або "Групи таблиць" не активний) система завантажується і працює в 1,5 рази швидше.

Осауленко Александр пишет:
Необходимо определиться, клиент тормозит или сервер. Я бы сначала посмотрел на запросы от клиента к серверу (профайлер от sql server).

Источник: Производительность системы
http://community.terrasoft.ua/forum/topic/5291

В этой записи в моем блоге я привожу пример как можно проанализировать время выполнения запросов и работы клиентской части CRM с помощью SQL Profiler:
Тема: Анализ быстродействия CRM с помощью SQL Profiler
http://community.terrasoft.ua/blogs/6030

Служба поддержки Террасофт пишет:
Для увеличения быстродействия открытия окон, при их разработке необходимо учитывать следующее:
1. Минимизировать логику в обработчиках событий OnPrepare, OnShow.
2. Не загромождать окна лишними контролами.
3. Использовать минимальную вложенность контролов.
4. Группировать контролы в отдельные фреймы, в зависимости от их смыслового назначения. Использовать центрирование контролов в фреймах по правому либо по левому краю.
5. Уменьшить использование подсветки записей в реестре. Использование подсветки значительно замедляет работу системы.
6. Отображать минимальное количество колонок в реестре, остальные скрывать.

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

Из личного примера: нужно было ускорить время открытия карточки редактирования задачи. После ранее внесенных изменений с моей стороны она открывалась секунд 5-6. Причину я нашел: подключал слишком громоздкие скрипты (например скрипт окна грида документов - wnd_DocumentsGridArea). Почистил подключаемые скрипты, перенес некоторые функции из подключенных скриптов в сам скрипт окна редактирования задачи. И как результат - окно начало открываться 1-2 секунды. Да, это была моя ошибка, но таким образом я узнал, что количество подключаемых скриптов тоже может влиять на быстродействие.

По этому поводу:

Служба поддержки Террасофт пишет:
Чем больше используется подключенных скриптов, тем больше времени затрачивается на инициализацию, следовательно уменьшается быстродействие работы системы.

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

Также, избегайте зацикливания при подключении скриптов.

Как отключить скрипт из основного скрипта, таким образом исключив затраты на его инициализацию во время загрузки CRM, я описал в следующем посте:
Тема: Обращение к переменным и методам скрипта
http://community.terrasoft.ua/forum/topic/6036

По этому поводу я задал следующий вопрос в Службу поддержки Terrasoft:

Кошкаров Андрей, задавая вопрос, пишет:
Подскажите какие плюсы/минусы использования скриптов и их методов этими способами, как может это повлиять на быстродействие системы:
1. Подключать нужный скрипт в текущий скрипт и обращаться к функциям из подключенного скрипта напрямую, например:
ExportAccountToClient(AccountID);

Минус: это что всегда при инициализации основного скрипта инициализируется и подключенный скрипт, который может быть довольно ресурсоемким.
2. Вызывать метод скрипта через получение этого скрипта из кэша или из БД (если не закеширован). Например:
var scrGeneral1CUtils = Services.GetSingleItemByUSI('scr_General1CUtils');
scrGeneral1CUtils.ScriptControl.Run('ExportAccountToClient', AccountID);

Плюс: что мы избегаем обязательной инициализации дополнительных скриптов при инициализации основного скрипта.

Ответ был полезным для меня:

Служба поддержки Террасофт пишет:
В общем, Вы описали один из методов оптимизации, который мы использовали при написании базовой конфигурации 3.3.2.
Из scr_Main было убрано явное и косвенное использование scr_UserReportCommon, в результате 3.3.2 стало запускаться почти в 2 раза быстрее, чем 3.3.1.

Из минусов второго варианта на ум приходит только то что в главном скрипте нельзя будет прямо использовать глобальные переменные подчиненного скрипта. Но если вспомнить про инкапсуляцию данных, это становится весьма незначительным минусом.
Так же, при использовании второго подхода мы бы посоветовали локально кешировать (в главном скрипте сохранять в переменной полученный экземпляр подчиненного скрипта) сервис полученный через GetSingleItemByUSI, т.к. если вызвать GetSingleItemByUSI второй раз, то и во второй раз будет проведена
полная инициализация подчиненного скрипта (и возможно всех его uses тоже, этот вопрос требует исследования).

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

scrGeneral1CUtils.ScriptControl.Run('ExportAccountToClient', AccountID);

а вот такой вариант:
scrGeneral1CUtils.ScriptControl.CodeObject.ExportAccountToClient(AccountID);

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

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

Из личного опыта:

Кошкаров Андрей пишет:
Благодаря использованию конструкций кода, вместо подключения скриптов к главному скрипту (пример):
function GetIsOLAPControlIstalled_() {
        if (!Assigned(Main.scrOLAPUtils)) {
                Main.scrOLAPUtils = Services.GetSingleItemByUSI('scr_OLAPUtils');
        }
        return Main.scrOLAPUtils.ScriptControl.CodeObject.GetIsOLAPControlIstalled();
}

....
        if ((WorkspaceUSI == 'wnd_OLAPWorkspace') &&
                (!GetIsOLAPControlIstalled_())) {
....
  • получилось ускорить время загрузки CRM с активным разделом "Контрагенты".
  • Показатели были получены при запуске на тестовом компьютере (процессор Intel Celeron 600 MHz, 256 Мб ОЗУ):
    До:
    Серверная часть (сек)| Клиентская часть (сек) | Общее время (сек)
    1.581 | 196.898 | 198.409
    После:
    Серверная часть (сек)| Клиентская часть (сек) | Общее время (сек)
    1.274 | 123.109 | 124.329
    Итого общее время было уменьшено с приблизительно 3 мин. 20 сек до 2 мин. 4 сек., благодаря уменьшению времени на выполнение операций, выполняемых клиентской частью CRM.

  • ускорить время открытия карточки редактирования записи контрагента:
  • До:
    Серверная часть (сек)| Клиентская часть (сек) | Общее время (сек)
    0.019 | 18.848 | 18.863
    После:
    Серверная часть (сек)| Клиентская часть (сек) | Общее время (сек)
    0.021 | 6.463 | 6.481
    Итого общее время было уменьшено с приблизительно 19 сек до 6.5 сек.

  • ускорить время инициализации раздела "Задачи":
  • До:
    Серверная часть (сек)| Клиентская часть (сек) | Общее время (сек)
    2.875 | 27.772 | 30.620
    После:
    Серверная часть (сек)| Клиентская часть (сек) | Общее время (сек)
    0.077 | 18.441 | 18.509
    Итого общее время было уменьшено с приблизительно 28 сек до 18.5 сек.

  • ускорить время инициализации карточки редактирования задачи:
  • До:
    Серверная часть (сек)| Клиентская часть (сек) | Общее время (сек)
    0.073 | 21.738 | 21.804
    После:
    Серверная часть (сек)| Клиентская часть (сек) | Общее время (сек)
    0.039 | 4.087 | 4.122
    Итого общее время было уменьшено с приблизительно 22 сек до 4 сек.

Кому то будет полезна информация о процессе инициализации окон в разделе и в окне редактирования (последовательность, наиболее ресурсоемкие операции):

Служба поддержки Террасофт пишет:
Процесс инициализации окон в разделе:
1. Десериализация – восстановление сохраненных объектов. Если раздел отображается впервые – происходит считывание данных из БД. Если раздел уже отображался – происходит считывание данных из Cache. В том случае, если системные характеристики компьютера достаточно низкие данная процедура будет происходит сравнительно медленно.
2. Инициализация групп, основного реестра, глобальных переменных, ссылок на наборы данных и открытие набора данных групп.
Отправной точкой для отображения данных является открытие набора данных групп с позиционированием на корневой группе (function OpenGroupsDataset()).
3. Вызов метода Show() для каждого элемента раздела.
4. Вызов метода Prepare() для каждого элемента раздела.
5. Фильтрация реестра записей.
6. Фильтрация текущего представления
7. Заполнение реестра данными
8. Refresh активной детали.

Процесс инициализации карточки редактирования:
1. Десериализация.
2. Вызов метода Show() окна.
3. Вызов метода Prepare() окна.

Наиболее ресурсоемкие операции –десериализация, прорисовка контролов, подтягивание данных.

С функциями, используемыми при инициализации Вы можете ознакомиться в SDK.

Как снизить время первоначального открытия разделов. Несколько видоизменил ответ от Раловец Ольги, добавив возврат в первоначально загружаемый раздел. Также внесены были замечания от других пользователей:

Раловец Ольга пишет:
Пример реализации из проекта.
function wnd_MainOnShow(Window) {
    Self.BeginUpdate();
    var WspCodesArray = Main.UserSettingsWindow.Attributes('WorkspacesForCaching').split(' ');
    for (var i in WspCodesArray) {
        var WorkspaceWindowCode = WspCodesArray[i];
        if (IsEmptyValue(WorkspaceWindowCode)) {
            continue;
        }
        var WorkspaceWindow = GetWorkspaceByUSI(WorkspaceWindowCode);
        wndWorkspace.Window = WorkspaceWindow;
        var EditWindowUSI = '';
        if (Assigned(WorkspaceWindow.ComponentsByName('wndGridData'))) {
            EditWindowUSI =
                WorkspaceWindow.ComponentsByName('wndGridData').Window.Attributes('EditWindowUSI');
        }
        if(IsEmptyValue(EditWindowUSI)) {
            continue;
        }
        var Attrs = GetNewDictionary();
        AddRequiredValuesToDictionary(Attrs, GUID_NULL, false, true);
        var EditWindow = ShowEditWindowEx(EditWindowUSI, Attrs, System.EmptyValue, true, true);
        EditWindow.Close();
    }
    Self.EndUpdate();
}

В данном случае требовалось кэшировать при запуске системы разделы, отмеченные пользователем в настройках, и их карточки редактирования. Вместо строчки
var WspCodesArray = Main.UserSettingsWindow.Attributes('WorkspacesForCaching').split(' ');
можно явно указать нужные разделы, задав массив WspCodesArray, элементами которого являются коды главных окон этих разделов, например, 'wnd_ContactsWorkspace'. Если карточки редактирования Вас не интересуют, то все сведется к

function wnd_MainOnShow(Window) {
    //предварительная инициализация разделов
    Self.BeginUpdate();
    var OriginalWorkspaceWindow = wndWorkspace.Window;
    var WspCodesArray = new Array('wnd_AccountsWorkspace',
            'wnd_ContactsWorkspace', 'wnd_TasksWorkspace',
            'wnd_OpportunitiesWorkspace', 'wnd_ContractsWorkspace',
            'wnd_DocumentsWorkspace', 'wnd_InvoicesWorkspace',
            'wnd_MailWorkspace');
    for (var i in WspCodesArray) {
            var WorkspaceWindowCode = WspCodesArray[i];
            if (IsEmptyValue(WorkspaceWindowCode)) {
                    continue;
            }
            var WorkspaceWindow = GetWorkspaceByUSI(WorkspaceWindowCode);
            wndWorkspace.Window = WorkspaceWindow;        
    }
    wndWorkspace.Window = OriginalWorkspaceWindow;
    Self.EndUpdate();
}

Данная функция описана в скрипте scr_Main. Проект был реализован на базе версии 3.2.1.

Источник: как ускорить первоначальное открытие разделов
http://community.terrasoft.ua/forum/topic/4285

Нравится

Поделиться

3 комментария

Комментарий от партнера вендору: более чем ценная информация. для каждого из нас. не секрет, что темпы развития продуктов ТС опережают возможности документаторов и техподдержки ТС. Опережают они и наши возможности. Намного опережают. В ходе работы часто сталкиваемся с ситуацией когда надо перелопатить "единого слова ради тысячи тонн словесной руды" (форумы на Сообществе, документация к продуктам) и...все равно решения нет. Очень нужна публикация такого рода обобщенных наблюдений. в том числе от техподдержки ТС, когда вы, коллеги, отвечая по запросам, находите ответ или решение, не задокументированное ранее. Спасибо.

А еще ...
В базовой функции RefreshDetails все вставляют толпу if'ов и условия там идут вида: pgDetails.ActivePage.Name == pgMyDetail.Name
Для меня до сих пор, кстати, загадка зачем берут именно свойство объекта, а не строку )
это раз. а два - это ifы необходимо заменить на switch. В данном контексте switch работает быстрее. Конечно же это просто капля по сравнению со всем другим, но все-таки ;-)

Функция выводит список скриптов и функций, которые используются в указанном скрипте: перенес сюда.

Показать все комментарии

Здравствуй, человек-читатель блогов на Community.

Хочу рассказать о своем недавнем опыте оптимизации курсора в SQL Server.
Первое, что нужно знать, курсор – это не хорошо, а плохо. Где есть возможность заменить курсор на INSERT SELECT или на использование временной таблицы, там нужно это сделать (за редким исключением). Курсор – это почти всегда дополнительные ресурсы сервера и резкое падение производительности по сравнению с другими решениями.
Второе, иногда без курсора не обойтись – там где не обойтись без построчного прохода по результату выборки. Вот в таких случаях очень важно правильно создать нужный тип курсора – тот, который соответствует решаемой задаче. Общий синтаксис объявления курсора имеет вид:

DECLARE cursor_name CURSOR
[ LOCAL | GLOBAL ]
[ FORWARD_ONLY | SCROLL ]
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
[ TYPE_WARNING ]
FOR select_statement
[ FOR UPDATE [ OF column_name [ ,...n ] ] ] [;]

Остановлюсь на первых трех строчках ключевых параметров.
    LOCAL или GLOBAL:    если хотим, чтобы курсор был доступен другим процедурам, функциям, пакетам в рамках нашей сессии, то GLOBAL – в этом случае за удалением курсора следим сами (команда DEALLOCATE). Во всех остальных случаях (т.е. в подавляющем своем большинстве) – LOCAL. Внимание, по умолчанию создается именно GLOBAL курсор!
    FORWARD_ONLY или SCROLL: если хотим ходить по курсору, как ненормальные, туда-сюда, то SCROLL, иначе – FORWARD_ONLY. Внимание, по умолчанию создается SCROLL курсор!
    STATIC или KEYSET, DYNAMIC, FAST_FORWARD: если хотим, чтобы при проходе по курсору отображалась актуальная информация из таблицы (т.е., если после открытия курсора, мы поменяли информацию в одном из полей таблицы и хотим, чтобы при проходе по курсору в нужной строчке курсора была уже обновленная информация), то используем или KEYSET (если КАЖДАЯ таблица, участвующая в выборке, имеет уникальный индекс) или DYNAMIC (самый медленный тип). Если же нам нужен снимок результата выборки после открытия курсора – STATIC (самый быстрый тип – копия результата выборки копируется в базу tempdb и работаем уже с ней). FAST_FORWARD = KEYSET+FORWARD_ONLY+READ_ONLY – пацаны из инета пишут, что STATIC дольше открывается (т.к. создается копия в tempdb), но быстрее работает, а FAST_FORWARD – наоборот. Так что если количество записей велико (насколько большое показывает практика), то применяем STATIC, иначе – FAST_FORWARD. Внимание, по умолчанию создается DYNAMIC курсор.

Таким образом, для большого кол-ва записей в большинстве случаев мой выбор:
DECLARE cursor_name CURSOR LOCAL FORWARD_ONLY STATIC FOR
select_statemen
t

для небольшого кол-ва записей:
DECLARE cursor_name CURSOR LOCAL FAST_FORWARD FOR
select_statement

Теперь перейдем к практике (что собственно и подтолкнуло меня к писанине сего).
Испокон веков при объявлении курсора я применял конструкцию DECLARE ... CURSOR LOCAL FOR...
При разработке интеграции с одной очень нехорошей базой, в которой нет ни одного индекса и не одного ключа, я применил тот же подход при объявлении курсоров, что и всегда. Выборка одного курсора содержала 225 000 записей. В результате процесс импорта данных из такой базы занял 15 часов 14 минут !!! И хотя импорт и был первичный (т.е. одноразовый), но даже для нормального тестирования такого импорта потребовалось бы несколько суток! После замены вышеназванной конструкции при объявлении курсора на DECLARE .. CURSOR LOCAL FORWARD_ONLY STATIC FOR.. весь процесс импорта занял ... внимание ... 10 минут 5 секунд !!! Так что игра точно стоит свеч.
Хочу повториться, что идеальный вариант - это все же не использовать курсоры вообще - для СУБД MS SQL намного роднее реляционный, а не навигационный подход.

Нравится

Поделиться

10 комментариев

Артем, классно, сколько пишу на T-SQL почти никогда не применял данные типы курсоров - всегда считал что это медленно и все старался заменить на insert select и декартово произведение, но оказывается эти параметры сильно ускоряют! Интересно! Надо будет запомнить. Есть правда еще один способ который ускоряет. Как известно если явно не стартовать транзакцию, то все запросы выполняются в рамках неявных транзакций, что сильно "бьет" по производительности, так вот если завести счетчик и стартовать транзакцию и коммитить после каждой 1000-й вставки, то скорость возрастает на порядки. Интересно попробовать это в случае с LOCAL FORWARD_ONLY STATIC :)
Только для надежности надо установить
SET CURSOR_CLOSE_ON_COMMIT OFF
А то курсор закроется после коммита...

Полезно, спасибо!

 

Артем, спасибо! Очень полезная информация.

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

"Репко Артём" написал:если хотим ходить по курсору, как ненормальные, туда-сюда, то SCROLL

Артем, объясни, пожалуйста, как это понимать?

"Раловец Ольга" написал:как это понимать?

Ольга, простите за вольный стиль. Я имел ввиду, что если курсор SCROLL, то по нему можно двигаться как вперед, так и назад, а если FORWARD_ONLY - только вперед.

Думаю, Артём имел в виду использование не только с начала и до конца FETCH NEXT, а и таких возможностей, как FETCH FIRST, FETCH LAST, FETCH PRIOR, FETCH ABSOLUTE n, FETCH RELATIVE n.

Если коротко, цитата из хелпа по SQL:

Cursor Classifications
A cursor can be classified by the fetch options it supports:

Forward-only
Rows must be fetched serially from the first row to the last row. FETCH NEXT is the only fetch operation allowed.

Scrollable
Rows can be randomly fetched from anywhere in the cursor. All the fetch operations are allowed (except that dynamic cursors do not support fetch absolute).

Scrollable cursors are especially useful for supporting online applications. A cursor can be mapped to a grid or list box in the application. As the user scrolls up and down and all around the grid, the application uses scroll fetches to retrieve the rows from the cursor the user wants to see.

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

Спасибо, Артем, спасибо, Олег. :)

"Репко Артём" написал:Ольга, простите за вольный стиль

Ваш стиль кажется мне приемлемым.

Коллеги, если всем понравилось, голосуем! +1
Артёму большое спасибо!

:twisted:

Огромнейшее спасибо! На "раскидывание" импортированных данных по таблицам (на 30 000 записей) вместо почти 5 часов ушло 50 минут.

Показать все комментарии

Данное сообщение будет полезно всем, кто занимается экспортом в Excel, особенно при выгрузке больших объемов данных.

Сам принцип довольно прост - формируем двухмерный вариантный массив, указываем область в Excel, куда необходимо его разместить и выгружаем. Самой проблемной остается задача заполнения массива. Для выгрузки из Delphi есть множество примеров/ Привожу один из них:

Но как сделать то же самое, только на языке JavaScript в конфигурации Terrasoft CRM и какая при этом будет скорость?

Привожу пример кода:

function Main() {
      var Excel = new ActiveXObject('Excel.Application');
      var Workbook = Excel.Workbooks.Add();
      var Sheet = Workbook.Sheets.Add();
      var StartRowNumber = 1;
      var StartColNumber = 1;
      var RowsCount = 10000;
      var ColumnsCount = 200;
      var Range = GetRangeObject(RowsCount, ColumnsCount);
      for (var X = 1; X = RowsCount; X++) {
            for (var Y = 1; Y = ColumnsCount; Y++) {
                  Range.Value(X, Y) = X * Y;
            }
      }
      var TopLeftRangeValue = GetRangeValue(StartRowNumber, StartColNumber);
      var BottomRightRangeValue = GetRangeValue(StartRowNumber + RowsCount - 1,
            StartColNumber + ColumnsCount - 1);
      Log.Write(1, 'Начало вставки записей в диапазон "' + TopLeftRangeValue +
            ':' + BottomRightRangeValue + '" = ' + RowsCount * ColumnsCount);
      Sheet.Range(TopLeftRangeValue, BottomRightRangeValue) =
            Range.ValuesAsArray;
      Log.Write(1, 'Конец вставки записей');
      Excel.Visible = true;
}

Для запуска в скрипт необходимо включить скрипт scr_UserReportCommon в котором находятся функции GetRangeValue() и GetRangeObject().
Функцию GetRangeValue нужно заменить на новую:
function GetRangeValue(RowNumber, ColumnNumber) {
      if ((RowNumber 1) || (ColumnNumber 1)) {
          return false;
      }
      var MaxCharNumber = 26;
      if (ColumnNumber > MaxCharNumber) {
            var FloorValue = Math.floor((ColumnNumber - 1)/MaxCharNumber);
            var FirstChar = String.fromCharCode(64 + FloorValue);
            var ColumnNumber = ColumnNumber - FloorValue * MaxCharNumber;
      } else {
            var FirstChar = '';
      }
      var RangeColumn = FirstChar + String.fromCharCode(64 + ColumnNumber);
      return RangeColumn + RowNumber;
}

Принцип действия следующий:
1) Создаем массив необходимых размеров:
      var Range = GetRangeObject(RowsCount, ColumnsCount);

2) Заполняем массив данными:
      for (var X = 1; X = RowsCount; X++) {
            for (var Y = 1; Y = ColumnsCount; Y++) {
                  Range.Value(X, Y) = X * Y;
            }
      }

3) Определяем адрес левой верхней и правой нижней ячеек по номерам строки и колонки (например, получаем следующие значения "A1", "GR10000"):
      var TopLeftRangeValue = GetRangeValue(StartRowNumber, StartColNumber);
      var BottomRightRangeValue = GetRangeValue(StartRowNumber + RowsCount - 1,
            StartColNumber + ColumnsCount - 1);

4) И самое главное - запускаем вставку данных из массива:
      Sheet.Range(TopLeftRangeValue, BottomRightRangeValue) =
            Range.ValuesAsArray;

При запуске выводит в лог следующее сообщение:
[09.03.04 09.50.32.342] (W) Начало вставки записей в диапазон "A1:GR10000" = 2000000
[09.03.04 09.50.36.628] (W) Конец вставки записей

При запуске тестового примера оказалось, что данный способ заполняет 2 000 000 ячеек не более чем за 5 секунд.

При выгрузке старайтесь, чтобы объем размер области совпадал с размером массива.
И не забывайте, что в Excel существуют ограничения на количество строк и колонок в листе - строк не более 65536, а колонок - не более 256.

Нравится

Поделиться

5 комментариев

Не совсем так. В последней версии Excel колонок и строк может быть больше. Отсюда важный момент - при работе с очень большими файлами вариантный массив может не создасться, если создавать его по всей используемой области. Пишу просто потому что сам один раз на такое нарвался :)

Думаю, что при работе с большими объемами данных могут быть проблемы, которые, связаны с ограниченными ресурсами машины (например, памяти). В этом случае можно разделять массив данных на несколько более мелких блоков, каждый из которых необходимо будет вставлять в Excel отдельно.

Одним из быстрых способов также будет простой экспорт в csv формат

Интересно, а как можно организовать если на этапе создание объекта Range не известно количество строк?

И все же одним из быстрых способов будет простой экспорт в csv формат. Или же можно формировать результат непосредственно в формате Open XML для последних версий MS Office. Хотя с Open XML конечно сложнее.

Показать все комментарии