Сообщество программистов Autodesk в СНГ

ADN Club => Revit API => Тема начата: Alex25 от 19-03-2020, 18:27:27

Название: Оптимизация работы нахождения ближайшего уровня элемента.
Отправлено: Alex25 от 19-03-2020, 18:27:27
Добрый день. Выделяю все элементы на виде рамкой - получаю 22 тысячи. Нахожу у каждого элемента ближайший уровень снизу. В try обрабатываются- FamilyInstance, в Catch -системные (трубы ,воздуховоды и тд). Имею одну транзакцию. В  начале открываю и в самом конце (после цикла по всем элементам). Если это FamilyInstance нахожу ближайший уровень  - высчитываю новое смещение - и устанавливаю элементу новый уровень - записываю  значение параметра "этаж" с нового уровня в параметр "этаж"  элемента. Если это системное , все аналогично , кроме смещение (его не будет). Пишу много if(ов) так, как есть такие трудности  - точка расчета площади, на грани  и тд ( мне это нужно  для нового смещение). Например, если семейство имеет "точку расчета площади", то я беру не LocationPoint.Z,  а "GetSpatialElementCalculationPoint().Z" и смещение задаю по "BoundingBoxXYZ.Min.Z" , чтобы не "скакало". . Фотографии кода прикладываю. 
Статистика:
- файл ВК 3.5 тысячи- обработал за 2 минуты.
- файл ОВ 22 тысячи - обработал за 1 час 20 минут.
Причем, в начале к каждому елементу применял две транзакции и коллектор искал заново , НО на время это никак не повлияло - 1 час 20 мин , как и был.
С результатом работы, пока вопросов нет, но время хотелось бы сократить.
1 вопрос - как сократить время?
2 вопрос - почему при изменение с двух транзакций на одну общую в программе - результат по времени одинаковый ?
(https://i.postimg.cc/xkWt7wst/1.png) (https://postimg.cc/xkWt7wst)

(https://i.postimg.cc/D4h5fq3G/2.png) (https://postimg.cc/D4h5fq3G)

(https://i.postimg.cc/9RZJjLKV/3.png) (https://postimg.cc/9RZJjLKV)
Название: Re: Оптимизация работы нахождение ближайшего уровня снизу.
Отправлено: Александр Ривилис от 20-03-2020, 00:41:38
В try обрабатываются- FamilyInstance, в Catch -системные (трубы ,воздуховоды и тд).
Если есть возможность - откажитесь от обработки в catch. Обработка прерываний в .NET - это достаточно медленная процедура. По опыту программирования в AutoCAD я в этом убедился. Есть два метода Database.GetObjectId который может вызывать прерывание и метод Database.TryGetObjectId, который не вызывает прерывания, а возвращает false если ничего не нашёл, или true если нашел. Разница в скорости работы в случае если прерывания достаточно часто возникают может быть на порядок, а то и на два...
Название: Re: Оптимизация работы нахождения ближайшего уровня элемента.
Отправлено: Alex25 от 20-03-2020, 10:54:57
Как  думаете , если заменить try catch на if, будет быстрее?
А как количество if (ов) в программе  влияет на время?
Название: Re: Оптимизация работы нахождения ближайшего уровня элемента.
Отправлено: Александр Ривилис от 20-03-2020, 10:59:55
Как  думаете , если заменить try catch на if, будет быстрее?
А как количество if (ов) в программе  влияет на время?
Будет не просто быстрее, а на порядки быстрее если исключение возникает часто. Раскрутка стека исключений очень ресурсоемкая процедура. Поэтому логика программа не должна опираться на исключения. Это действительно должен быть исключительный случай, когда вызывается исключение (т.е. попадаем в блок catch).
Количество if-ов практически никак не влияет на скорость выполнения задачи. Они просто обеспечивают ветвление программы.
Название: Re: Оптимизация работы нахождения ближайшего уровня элемента.
Отправлено: Александр Ривилис от 20-03-2020, 11:04:52
Alex25,
Почитай: https://docs.microsoft.com/ru-ru/dotnet/standard/exceptions/best-practices-for-exceptions (https://docs.microsoft.com/ru-ru/dotnet/standard/exceptions/best-practices-for-exceptions)
Цитата оттуда:
Цитировать
Обработка общих условий без выдачи исключений
Для условий, которые могут возникнуть, но способны вызвать исключение, рекомендуется реализовать обработку таким способом, который позволит избежать исключения. Например, при попытке закрыть уже закрытое подключение возникает InvalidOperationException. Этого можно избежать, используя оператор if для проверки состояния подключения перед попыткой закрыть его.
 C#
if (conn.State != ConnectionState.Closed) { conn.Close(); } 
Если состояние подключения перед закрытием не проверяется, исключение InvalidOperationException можно перехватить.
 C#
try { conn.Close(); } catch (InvalidOperationException ex) { Console.WriteLine(ex.GetType().FullName); Console.WriteLine(ex.Message); } 
Выбор конкретного способа зависит от того, насколько часто ожидается возникновение данного события.
 
  • Используйте обработку исключений, если событие не происходит очень часто, то есть если событие носит действительно исключительный характер и указывает на ошибку (например, в случае неожиданного конца файла). При использовании обработки исключений в обычных условиях выполняется меньше кода.
  • Если событие происходит регулярно в рамках нормальной работы программы, выполняйте проверку на наличие ошибок прямо в коде. Проверка на наличие распространенных условий ошибки позволяет выполнять меньший объем кода благодаря устранению исключений.
Название: Re: Оптимизация работы нахождения ближайшего уровня элемента.
Отправлено: Alex25 от 20-03-2020, 13:45:24

(https://i.postimg.cc/34yLnSR7/4.png) (https://postimg.cc/34yLnSR7)
Спасибо, кажется стало быстрее, но приходится отлавливать исключения. Элементов много - затратно по времени.
(https://i.postimg.cc/ZWYpqRX2/5.png) (https://postimg.cc/ZWYpqRX2)
Название: Re: Оптимизация работы нахождения ближайшего уровня элемента.
Отправлено: Александр Ривилис от 20-03-2020, 13:48:34
Спасибо, кажется стало быстрее, но приходится отлавливать исключения.
Нужно по-максимуму добиться того, чтобы исключений не было.
Название: Re: Оптимизация работы нахождения ближайшего уровня элемента.
Отправлено: Alex25 от 20-03-2020, 14:36:29
Это магия ?? в 11,5 раз стало быстрее , после замены try catch на if
(https://i.postimg.cc/7Ct1CQcg/6.png) (https://postimg.cc/7Ct1CQcg)
Спасибо большое
Название: Re: Оптимизация работы нахождения ближайшего уровня элемента.
Отправлено: Александр Ривилис от 20-03-2020, 14:46:42
Это магия ?? в 11,5 раз стало быстрее , после замены try catch на if
Я же предупреждал. :) Стараюсь не лезть в те темы, в которых не разбираюсь. Но в данном случае это общесистемное правило, которое касается всего .NET и даже native C/C++. Нельзя использовать исключения/прерывания в логике работы. Это очень резко уменьшает скорость работы программы.