doctorraz Posted August 23, 2021 Report Share Posted August 23, 2021 (edited) Простенький код который считает блоки в активном пространстве Спойлер //#if DEBUG using System.Diagnostics; #if NC using Teigha.DatabaseServices; using Teigha.Runtime; using HostMgd.ApplicationServices; using HostMgd.EditorInput; #else using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; #endif namespace drz { public class TestPerfNano { /// <summary> /// Тест чертеж через БД /// </summary> [CommandMethod("t-TestPerfNC-DB")] public void CountBlcDB() { Document doc = Application.DocumentManager.MdiActiveDocument; //Database db = doc.Database; if (doc == null) return; Editor ed = doc.Editor; string sFilPath = "c:\\Temp\\_tc\\4000 блоков +660 000 примитивов.dwg"; Stopwatch s = new Stopwatch(); int cnt = 0; s.Start(); using (Database db = new Database(false, true)) { db.ReadDwgFile(sFilPath, FileOpenMode.OpenForReadAndWriteNoShare, false, "" ); using (Transaction tr = db.TransactionManager.StartTransaction()) { ObjectId SpaceId = db.CurrentSpaceId;//ID активного пространства BlockTableRecord btrs = tr.GetObject( SpaceId, OpenMode.ForRead ) as BlockTableRecord;//получаем запись BlockTableRecord активного пространства foreach (ObjectId brId in btrs)//в активном пространстве перебираем все что в нем находится { BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;//пытаемся получить вставку блока if (br != null) { BlockTableRecord btr = tr.GetObject( br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;//по вставке получаем описание блока if (!btr.IsFromExternalReference && !btr.IsDependent )//если не внешняя сылка и не зависимый блок, считаем { cnt++; } } } s.Stop(); ed.WriteMessage( "\nEnum Before Commit {0}\n", s.Elapsed); s.Start(); tr.Commit(); s.Stop(); ed.WriteMessage( "\nEnum After Commit {0}\n", s.Elapsed); s.Start(); } s.Stop(); ed.WriteMessage( "\nEnum блоков {0} за {1}\n", cnt, s.Elapsed ); s.Start(); //БД не сохраняем, бросаем так(( } s.Stop(); ed.WriteMessage( "\nTotal блоков {0} за {1}\n", cnt, s.Elapsed ); } /// <summary> /// Тест в активном чертеже /// </summary> [CommandMethod("t-TestPerfNC")] public void CountBlc() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; if (doc == null) return; Editor ed = doc.Editor; Stopwatch s = new Stopwatch(); int cnt = 0; PromptKeywordOptions pko = new PromptKeywordOptions( "\nСпособ выбора блоков? "); pko.AllowNone = false; pko.Keywords.Add("Enum"); pko.Keywords.Add("Selset"); pko.Keywords.Default = "Selset"; PromptResult pr = ed.GetKeywords(pko); if (pr.StringResult == "Selset") { s.Start(); LayoutManager layoutMgr = LayoutManager.Current; TypedValue[] filterlist = new TypedValue[2];//фильтр filterlist[0] = new TypedValue(0, "INSERT");//только блоки filterlist[1] = new TypedValue(410, layoutMgr.CurrentLayout);//только в текущем пространстве SelectionFilter filter = new SelectionFilter(filterlist); PromptSelectionResult psr = ed.SelectAll(filter); if (psr.Status == PromptStatus.OK) { SelectionSet set = psr.Value; using (Transaction tr = db.TransactionManager.StartTransaction())//открываем транзакцию { foreach (ObjectId brId in set.GetObjectIds())//перебираем полученные ID блоков { BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;//получаем вставку блока if (br != null) { BlockTableRecord btr = tr.GetObject( br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;//по вставке получаем описание блока if (!btr.IsFromExternalReference && !btr.IsDependent )//если не внешняя сылка и не зависимый блок, считаем { cnt++; } } } s.Stop(); ed.WriteMessage( "\nSelSet Before Commit {0}\n", s.Elapsed ); s.Start(); tr.Commit(); s.Stop(); ed.WriteMessage( "\nSelSet After Commit {0}\n", s.Elapsed ); s.Start(); } } s.Stop(); ed.WriteMessage("\nSelSet блоков {0} за {1}\n", cnt, s.Elapsed ); s.Start(); } else if (pr.StringResult == "Enum") { s.Start(); using (Transaction tr = db.TransactionManager.StartTransaction()) { ObjectId SpaceId = db.CurrentSpaceId;//ID активного пространства BlockTableRecord btrs = tr.GetObject( SpaceId, OpenMode.ForRead ) as BlockTableRecord;//получаем запись BlockTableRecord активного пространства foreach (ObjectId brId in btrs)//в активном пространстве перебираем все что в нем находится { BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;//пытаемся получить вставку блока if (br != null) { BlockTableRecord btr = tr.GetObject( br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;//по вставке получаем описание блока if (!btr.IsFromExternalReference && !btr.IsDependent )//если не внешняя сылка и не зависимый блок, считаем { cnt++; } } } s.Stop(); ed.WriteMessage( "\nEnum Before Commit {0}\n", s.Elapsed); s.Start(); tr.Commit(); s.Stop(); ed.WriteMessage( "\nEnum After Commit {0}\n", s.Elapsed); s.Start(); } s.Stop(); ed.WriteMessage( "\nEnum блоков {0} за {1}\n", cnt, s.Elapsed ); s.Start(); } else { ed.WriteMessage("\nОтмена"); return; } s.Stop(); ed.WriteMessage( "\nBefore Regen {0}\n", s.Elapsed ); s.Start(); ed.Regen(); s.Stop(); ed.WriteMessage( "\nTotal {0}", s.Elapsed ); } } } //#endif двумя способами: SelectAll(filter) ("Selset"), по фильтру получает все блоки с активного пространства, потом в цикле по найденному получает их BlockTableRecord и заодно считает Перебором ("Enum") тупо перебором Всех примитивов пространства в цикле. ------------------- Собственно в чем у меня затыка, если количество примитивов не превышает некоторой "критической" массы, перебором получается даже быстрее.. Но если примитивов в чертеже много.... в аттаче файлик примера, 4000 блоков и 660 000 примитивов Способ "Selset" в nanoCAD работает даже быстрее, чем в АК В нано: Команда: DRZ-TESTPERFNC drz-TestPerfNC - drz-TestPerfNC Способ выбора блоков? [Enum/Selset] <Selset>: SelSet Before Commit 00:00:04.5189256 SelSet After Commit 00:00:04.5193736 SelSet блоков 4000 за 00:00:04.5193938 Before Regen 00:00:04.5193952 Total 00:00:08.2492307 В АК: Команда: DRZ-TESTPERFNC Способ выбора блоков? [Enum/SelSet] <SelSet>: SelSet SelSet закрылись через 00:00:00.8552151 SelSet блоков 4000 за 00:00:00.8552159 SelSet перед Regen через 00:00:00.8552159 Выполняется регенерация модели. Total 00:00:18.0264183 Весьма неплохо Но все меняется если "Enum" В АК: Команда: DRZ-TESTPERFNC Способ выбора блоков? [Enum/SelSet] <SelSet>: Enum SelSet закрылись через 00:00:01.0967135 Enum блоков 4000 за 00:00:01.0967144 SelSet перед Regen через 00:00:01.0967144 Выполняется регенерация модели. Total 00:00:18.2236430 Как видим время обработки практически не изменилось, т.е. не зависит от способа Забегая вперед скажу, что на небольшом количестве примитивов, нано даже быстрее АК, и Enun быстрее Selset Enum в nano: Команда: DRZ-TESTPERFNC drz-TestPerfNC - drz-TestPerfNC Способ выбора блоков? [Enum/Selset] <Selset>: Enum Enum Before Commit 00:09:14.6225632 Enum After Commit 00:09:14.7562459 Enum блоков 4000 за 00:09:14.7567482 Before Regen 00:09:14.7567482 Total 00:09:15.0192324 Это фиаско((((. Убойное время, в разы дольше, чем АК и нано по Selset Обратите внимание, что в последнем тесте Before Regen практически равен общему времени, такое ощущение, что нана делал реген на каждой итерации цикла, поэтому так упала производительность. ------------------ У кого какие мысли по поводу? ------- В аттаче: dll для тестов, подгрузить можно начиная с АК2018 и нано 20.1; нелегкий файлик примера 4000 блоков +660 000 примитивов.zip test_NC AnyCPU.dll.zip test_AC2021 AnyCPU.dll.zip Edited August 24, 2021 by doctorraz коментарии к коду, как обещал 1 1 Quote Link to comment Share on other sites More sharing options...
EdwardSt Posted August 23, 2021 Report Share Posted August 23, 2021 Тут неплохо было бы в отладчике глянуть какая именно из операций тормозит. Но осторожно предположил бы следующее: 1. В случае с <Selset> однократно производится операция установки фильтра (пространство + тип объекта) однократно формируется список объектов чертежа в соответствии с этим фильтром циклически (4000 раз) для каждого из отфильтрованных объектов-блоков осуществляется прямой запрос параметров из таблицы описаний; 2. В случае с <Enum> сначала формируется список описаний блоков, присутствующих в текущем пространстве (т.е., за кадром производится перебор всех элементов, отфильтровывание блоков, внесение в результирующий список ID из таблицы блоков, если такого ID еще нет) - итого, дополнительно к фильтру блоков еще пусть и минимальная, но их обработка обработка и формирование результирующего списка из всего 4-х (!) описаний; для каждого из описаний далее не совсем понятная конструкция (увы, ObjectARX не использую...) Спойлер ... foreach (ObjectId brId in btrs) { BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference; Предполагаю, что это формирование списка блоков, соответствующих элементу списка на первом шаге. и далее некая групповая операция над всем списком для каждого из отфильтрованных объектов-блоков осуществляется прямой запрос параметров из таблицы описаний; Если предположение для шагов 2 и 3 для случая <Enum> верны, то сопоставляя алгоритмы получаем, что простой и понятной прямой однократной функции отфильтровывания объектов по заданному фильтру соответствует комбинация отфильтровывания, обработки и раскладки объектов "по корзиночкам". Конечно, разбиение операции выборки на несколько операций выборок меньшего размера, не объясняет такой разницы в производительности (хотя и это стоит проверить!). Но суммарно это минимум в 2 раза увеличивает количество обращений к каждому элементу-блоку плюс время на минимальн6ую обработку. Возможно, проблема сконцентрирована в более узком месте, а именно в операции групповой обработки списка (что-то типа lambda в автолисп). Тогда можно говорить, что в АС такая функция реализована значительно эффективнее, чем в NC. 2 Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 23, 2021 Author Report Share Posted August 23, 2021 Я не зря стопватч перед регеном поставил.. Такое ощущение, что нана делает реген внутри транзакции? А зачем? Ведь вместо коммит и аборт может прилететь. В ком строке можно увидеть, что АК в транзакции занимается транзакцией, потом долго регенерирует. Нана жэ после прямого перебора на реген время не тратит... (((( добавлено через 1 минуту 1 час назад, EdwardSt сказал: для каждого из описаний далее не совсем понятная конструкция Завтра закомментирую код Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 23, 2021 Author Report Share Posted August 23, 2021 1 час назад, EdwardSt сказал: Но суммарно это минимум в 2 раза увеличивает количество обращений к каждому элементу-блоку плюс время на минимальн6ую обработку Обрати внимание, что АК селектом 0,85, а перебором 1,1, это грубо на треть дольше, т.е. 660к примитивов не значительно увеличили время.. А с учетом реген 18 секунд, разницы нет. Нана жэ только на перебор затратил 9 минут!!! Quote Link to comment Share on other sites More sharing options...
EdwardSt Posted August 23, 2021 Report Share Posted August 23, 2021 35 минут назад, doctorraz сказал: ... АК селектом 0,85, а перебором 1,1, это грубо на треть дольше, Как устроены потроха функции селект - для меня тайна. Я не думаю, что при работе программы автоматически ведутся списки под разные выборки. Поэтому, там в той или иной форме все равно имеет место последовательный перебор. Экономия может быть только за счет исключения повторного считывания одних и тех же данных, чем грешит ООП. Скорее всего считывание данных из БД чертежа происходит очень быстро. А вот формирование новых структур занимает больше времени (динамическое выделение памяти, расчет и установка кучи дополнительных параметров и т.д.). PS. Кстати, код на лиспе с аналогичным функционалом занял бы куда меньше места и выполнялся бы за вполне разумное время. Для примере прикладываю скрипт, которым часто пользуюсь. Он определяет, сколько каких блоков присутствует в чертеже, а также какой набор элементов в них входит. Ну и выплевывает это в ексель. У меня этот скрипт 50 сек лопатил чертеж и 15 сек изображал мультик с заполнением строк. ba1.lsp 2 Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 24, 2021 Author Report Share Posted August 24, 2021 хех походу реген не при делах перебор примитивов без открытия в редакторе Спойлер /// <summary> /// Тест чертеж через БД /// </summary> [CommandMethod("t-TestPerfNC-DB")] public void CountBlcDB() { Document doc = Application.DocumentManager.MdiActiveDocument; //Database db = doc.Database; if (doc == null) return; Editor ed = doc.Editor; string sFilPath = "c:\\Temp\\_tc\\4000 блоков +660 000 примитивов.dwg"; Stopwatch s = new Stopwatch(); int cnt = 0; s.Start(); using (Database db = new Database(false, true)) { db.ReadDwgFile(sFilPath, FileOpenMode.OpenForReadAndWriteNoShare, false, "" ); using (Transaction tr = db.TransactionManager.StartTransaction()) { ObjectId SpaceId = db.CurrentSpaceId;//ID активного пространства BlockTableRecord btrs = tr.GetObject( SpaceId, OpenMode.ForRead ) as BlockTableRecord;//получаем запись BlockTableRecord активного пространства foreach (ObjectId brId in btrs)//в активном пространстве перебираем все что в нем находится { BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;//пытаемся получить вставку блока if (br != null) { BlockTableRecord btr = tr.GetObject( br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;//по вставке получаем описание блока if (!btr.IsFromExternalReference && !btr.IsDependent )//если не внешняя сылка и не зависимый блок, считаем { cnt++; } } } s.Stop(); ed.WriteMessage( "\nEnum Before Commit {0}\n", s.Elapsed); s.Start(); tr.Commit(); s.Stop(); ed.WriteMessage( "\nEnum After Commit {0}\n", s.Elapsed); s.Start(); } s.Stop(); ed.WriteMessage( "\nEnum блоков {0} за {1}\n", cnt, s.Elapsed ); s.Start(); //БД не сохраняем, бросаем так(( } s.Stop(); ed.WriteMessage( "\nTotal блоков {0} за {1}\n", cnt, s.Elapsed ); } Результат в нано(((( t-TestPerfNC-DB - t-TestPerfNC-DB Enum Before Commit 00:09:05.4551557 Enum After Commit 00:09:05.7078582 Enum блоков 4000 за 00:09:05.7095503 Total блоков 4000 за 00:09:06.1136691 Копейка в копейку с обработкой в редакторе, походу оно так неспешно работает само по себе.. Спойлер 1 Quote Link to comment Share on other sites More sharing options...
Robink Posted August 24, 2021 Report Share Posted August 24, 2021 Перебор грубый. Надо сначала смотреть, что за объект, а потом уже пытаться открыть вхождение блока, если это оно. 1 Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 24, 2021 Author Report Share Posted August 24, 2021 8 минут назад, Robink сказал: Перебор грубый. Надо сначала смотреть, что за объект, а потом уже пытаться открыть вхождение блока, если это оно дык я получаю AS BlockReference, если null пошел за следующим ID BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;//пытаемся получить вставку блока как посмотреть по ID что это за объект? не открывая? ------------- на самом деле это не боевой код, просто сравнивал производительность Select и Enum в AutoCAD, большой разницы не обнаружил (учитывая, что SelectAll по всей видимости тоже не вдруг объекты получает, а я по ним второй раз в цикле прохожу и медленнее всего на 30% до regen), но.... когда запустил это в nano, был слегка шокирован Quote Link to comment Share on other sites More sharing options...
Robink Posted August 24, 2021 Report Share Posted August 24, 2021 13 минут назад, doctorraz сказал: дык я получаю AS BlockReference, если null пошел за следующим ID BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;//пытаемся получить вставку блока BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;//пытаемся получить вставку блока как посмотреть по ID что это за объект? не открывая? ------------- на самом деле это не боевой код, просто сравнивал производительность Select и Enum в AutoCAD, большой разницы не обнаружил (учитывая, что SelectAll по всей видимости тоже не вдруг объекты получает, а я по ним второй раз в цикле прохожу и медленнее всего на 30% до regen), но.... когда запустил это в nano, был слегка шокирован myObjectId.ObjectClass.Name или получить Entity, а потом if ent is BlockReference 1 1 Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 24, 2021 Author Report Share Posted August 24, 2021 (edited) 16 минут назад, Robink сказал: myObjectId.ObjectClass.Name Спасибо посмотрю... получаем myObjectId.ObjectClass.Name, проверяем, что нам прилетело, если то потом все равно идем получать BlockReference.... 16 минут назад, Robink сказал: или получить Entity, а потом if ent is BlockReference получаем Entity, проверяем на null ( в Spase не только графические примитивы живут) потом из сущности пытаемся получить блок и еще раз проверяем .. -------------- сейчас в коде пытаюсь сразу получить объект, одним разом открываю, что надо и один раз проверяю... как то так вижу добавлено через 3 минут 46 минут назад, Robink сказал: Надо сначала смотреть, что за объект, а потом уже пытаться открыть вхождение блока, если это оно. еще нюанс, смотря, как открывать.. если открывать так: BlockReference br = (BlockReference)t.GetObject(brId, OpenMode.ForWrite); то если это не вхождение блока прилетит исключение, а если, AS BlockReference, то будет просто null ---------------- но тема про то, что нано тухнет на этом коде Edited August 24, 2021 by doctorraz Quote Link to comment Share on other sites More sharing options...
Robink Posted August 24, 2021 Report Share Posted August 24, 2021 Лучше использовать конструкцию tr.GetObject(id, 0, false, true) не будет падения при открытии объектов на замороженных слоях 2 Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 25, 2021 Author Report Share Posted August 25, 2021 (edited) В 24.08.2021 в 11:27, Robink сказал: myObjectId.ObjectClass.Name Спасибо еще раз, что повернул мои мысли в нужном направлении. Не мог представить, что в нано так падает производительность при открытии объектов по сравнению с АК Спойлер else if (pr.StringResult == "enumRX") { s.Start(); RXClass dimenClass = RXObject.GetClass(typeof(BlockReference)); using (Transaction tr = db.TransactionManager.StartTransaction()) { ObjectId SpaceId = db.CurrentSpaceId;//ID активного пространства BlockTableRecord btrs = tr.GetObject( SpaceId, OpenMode.ForRead ) as BlockTableRecord;//получаем запись BlockTableRecord активного пространства foreach (ObjectId brId in btrs)//в активном пространстве перебираем все что в нем находится { if (!brId.ObjectClass.IsDerivedFrom(dimenClass)) { continue; } BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;//пытаемся получить вставку блока if (br != null) { BlockTableRecord btr = tr.GetObject( br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;//по вставке получаем описание блока if (!btr.IsFromExternalReference && !btr.IsDependent )//если не внешняя сылка и не зависимый блок, считаем { cnt++; } } } s.Stop(); ed.WriteMessage( "\nEnumRX Before Commit {0}\n", s.Elapsed); s.Start(); tr.Commit(); s.Stop(); ed.WriteMessage( "\nEnumRX After Commit {0}\n", s.Elapsed); s.Start(); } s.Stop(); ed.WriteMessage( "\nEnumRX блоков {0} за {1}\n", cnt, s.Elapsed ); s.Start(); } Результат в нано БрутФорс t-TestPerfNC - t-TestPerfNC Способ выбора блоков? [Enum/EnumRX/Selset] <Selset>: Enum Enum Before Commit 00:08:22.3782502 Enum After Commit 00:08:22.5114717 Enum блоков 4000 за 00:08:22.5119761 Before Regen 00:08:22.5119763 Total 00:08:22.7571060 Select t-TestPerfNC - t-TestPerfNC Способ выбора блоков? [Enum/EnumRX/Selset] <Selset>: SelSet Before Commit 00:00:04.4655408 SelSet After Commit 00:00:04.4665133 SelSet блоков 4000 за 00:00:04.4665284 Before Regen 00:00:04.4665301 Total 00:00:07.9702343 С проверкой типа перед открытием t-TestPerfNC - t-TestPerfNC Способ выбора блоков? [Enum/EnumRX/Selset] <Selset>: EnumRX EnumRX Before Commit 00:00:00.3934267 EnumRX After Commit 00:00:00.3942072 EnumRX блоков 4000 за 00:00:00.3942186 Before Regen 00:00:00.3942189 Total 00:00:03.8682973 PS вечером надо будет в АК проверить))) добавлено через 8 минут ну и конечно перебор объектов без открытия чертежа в редакторе, с проверкой типа t-TestPerfNC-DB - t-TestPerfNC-DB EnumRX Before Commit 00:00:03.5303153 EnumRXAfter Commit 00:00:03.6483379 EnumRX блоков 4000 за 00:00:03.6493636 Total блоков 4000 за 00:00:04.0326604 4 секунды это не 9 минут)))) офф нано конечно помедленнее чем АК, но это вполне объяснимо Edited August 25, 2021 by doctorraz поменял EnumRX на enumRX, две одинаковые заглавные низя в АК, в нано можно))) 1 Quote Link to comment Share on other sites More sharing options...
Robink Posted August 25, 2021 Report Share Posted August 25, 2021 А тут if (!brId.ObjectClass.IsDerivedFrom(dimenClass)) зачем отрицание? Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 25, 2021 Author Report Share Posted August 25, 2021 3 минуты назад, Robink сказал: if (!brId.ObjectClass.IsDerivedFrom(dimenClass)) зачем отрицание? дык Continue после проверки если не то что надо уходим на следующий круг добавлено через 2 минуты офф можно было инверсию не делать, но тогда надо скобку двигать, а я в них пока еще путаюсь 1 1 Quote Link to comment Share on other sites More sharing options...
Robink Posted August 25, 2021 Report Share Posted August 25, 2021 5 часов назад, doctorraz сказал: дык Continue после проверки если не то что надо уходим на следующий круг добавлено через 2 минуты офф можно было инверсию не делать, но тогда надо скобку двигать, а я в них пока еще путаюсь Я просто не пользовался continue, сначала не правильно понял как оно работает. Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 25, 2021 Author Report Share Posted August 25, 2021 Только что, Robink сказал: Я просто не пользовался continue, сначала не правильно понял как оно работает. иногда удобно, бывает 1 Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 25, 2021 Author Report Share Posted August 25, 2021 (edited) Спойлер Способ выбора блоков? [Enum/enumRX/Selset] <Selset>: RX EnumRX Before Commit 00:00:00.3504943 EnumRX After Commit 00:00:00.3518743 EnumRX блоков 4000 за 00:00:00.3518893 Before Regen 00:00:00.3518897 Выполняется регенерация модели. Total 00:00:10.8143822 Способ выбора блоков? [Enum/enumRX/Selset] <Selset>: E Enum Before Commit 00:00:00.9359413 Enum After Commit 00:00:01.0952777 Enum блоков 4000 за 00:00:01.0952828 Before Regen 00:00:01.0952828 Выполняется регенерация модели. Total 00:00:11.4400038 Команда: Способ выбора блоков? [Enum/enumRX/Selset] <Selset>: SelSet получен блоков 4000 за 00:00:00.9500616 SelSet Before Commit 00:00:00.9636216 SelSet After Commit 00:00:00.9647280 SelSet блоков 4000 за 00:00:00.9647331 Before Regen 00:00:00.9647331 Выполняется регенерация модели. Total 00:00:12.2005454 Спойлер Способ выбора блоков? [Enum/enumRX/Selset] <Selset>: rx EnumRX Before Commit 00:00:00.6613696 EnumRX After Commit 00:00:00.6656020 EnumRX блоков 4000 за 00:00:00.6674653 Before Regen 00:00:00.6674653 Total 00:00:05.3607580 Edited August 25, 2021 by doctorraz Quote Link to comment Share on other sites More sharing options...
EdwardSt Posted August 25, 2021 Report Share Posted August 25, 2021 6 часов назад, doctorraz сказал: 6 часов назад, Robink сказал: Я просто не пользовался continue, сначала не правильно понял как оно работает. иногда удобно, бывает Я бы сказал, что часто (а не иногда) бывает удобно. Прерывание текущей итерации в цикле - весьма востребованная функция при обработке массивов. Quote Link to comment Share on other sites More sharing options...
doctorraz Posted August 25, 2021 Author Report Share Posted August 25, 2021 В этом случае можно было без continue, скобки двигать не захотел))) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.