Перейти к содержанию

Падение производительности на foreach


Рекомендуемые сообщения

Простенький код который считает блоки в активном пространстве

 

Спойлер

//#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

Изменено пользователем doctorraz
коментарии к коду, как обещал
Ссылка на сообщение
Поделиться на другие сайты

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

Но осторожно предположил бы следующее:

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.

Ссылка на сообщение
Поделиться на другие сайты

Я не зря стопватч перед регеном поставил..

Такое ощущение, что нана делает реген внутри транзакции?

А зачем? Ведь вместо коммит и аборт может прилететь.

В ком строке можно увидеть, что АК  в транзакции занимается транзакцией, потом долго регенерирует.

Нана жэ после прямого перебора на реген время не тратит... ((((

добавлено через 1 минуту
1 час назад, EdwardSt сказал:

для каждого из описаний далее не совсем понятная конструкция

Завтра закомментирую код

Ссылка на сообщение
Поделиться на другие сайты
1 час назад, EdwardSt сказал:

Но суммарно это минимум в 2 раза увеличивает количество обращений к каждому элементу-блоку плюс время на минимальн6ую обработку

Обрати внимание, что АК селектом 0,85, а перебором 1,1, это грубо на треть дольше, т.е. 660к примитивов не значительно увеличили время..

А с учетом реген 18 секунд, разницы нет.

Нана жэ только на перебор затратил 9 минут!!!

Ссылка на сообщение
Поделиться на другие сайты
35 минут назад, doctorraz сказал:

... АК селектом 0,85, а перебором 1,1, это грубо на треть дольше,

Как устроены потроха функции селект - для меня тайна.

Я не думаю, что при работе программы автоматически ведутся списки под разные выборки. 

Поэтому, там в той или иной форме все равно имеет место последовательный перебор.

Экономия может быть только за счет исключения повторного считывания одних и тех же данных, чем грешит ООП.

Скорее всего считывание данных из БД чертежа происходит очень быстро.

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

 

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

Для примере прикладываю скрипт, которым часто пользуюсь.

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

Ну и выплевывает это в ексель.

У меня этот скрипт 50 сек лопатил чертеж и 15 сек изображал мультик с заполнением строк.

ba1.lsp

Ссылка на сообщение
Поделиться на другие сайты

хех походу реген не при делах B)

перебор примитивов без открытия в редакторе

Спойлер

/// <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

Копейка в копейку  с обработкой в редакторе, походу оно так неспешно работает само по себе..

Спойлер

image.png.bad77efd951641b7bdaf31636eef6db2.png

 

Ссылка на сообщение
Поделиться на другие сайты

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

Ссылка на сообщение
Поделиться на другие сайты
8 минут назад, Robink сказал:

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

дык я получаю AS BlockReference, если null пошел за следующим ID

BlockReference br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;//пытаемся получить вставку блока

 

как посмотреть по ID что это за объект? не открывая?

 

-------------

на самом деле это не боевой код, просто сравнивал производительность Select и Enum в AutoCAD, большой разницы не обнаружил (учитывая, что SelectAll по всей видимости тоже не вдруг объекты получает, а я по ним второй раз в цикле прохожу и медленнее всего на 30% до regen), но....

когда запустил это в nano, был слегка шокирован

Ссылка на сообщение
Поделиться на другие сайты
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

Ссылка на сообщение
Поделиться на другие сайты
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

 

----------------

но тема про то, что нано тухнет на этом коде

Изменено пользователем doctorraz
Ссылка на сообщение
Поделиться на другие сайты

Лучше использовать конструкцию

tr.GetObject(id, 0, false, true)

не будет падения при открытии объектов на замороженных слоях

Ссылка на сообщение
Поделиться на другие сайты
В 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 минут))))

офф нано конечно помедленнее чем АК, но это вполне объяснимо

 

Изменено пользователем doctorraz
поменял EnumRX на enumRX, две одинаковые заглавные низя в АК, в нано можно)))
Ссылка на сообщение
Поделиться на другие сайты
3 минуты назад, Robink сказал:

if (!brId.ObjectClass.IsDerivedFrom(dimenClass))

зачем отрицание?

дык Continue после проверки

если не то что надо уходим на следующий круг

добавлено через 2 минуты

офф можно было инверсию не делать, но тогда надо скобку двигать, а я в них пока еще путаюсь biglol.gif.308e88256bcb2394d09018c4dc1786ed.gif

Ссылка на сообщение
Поделиться на другие сайты
5 часов назад, doctorraz сказал:

дык Continue после проверки

если не то что надо уходим на следующий круг

добавлено через 2 минуты

офф можно было инверсию не делать, но тогда надо скобку двигать, а я в них пока еще путаюсь biglol.gif.308e88256bcb2394d09018c4dc1786ed.gif

Я просто не пользовался continue, сначала не правильно понял как оно работает.

Ссылка на сообщение
Поделиться на другие сайты
Только что, Robink сказал:

Я просто не пользовался continue, сначала не правильно понял как оно работает.

иногда удобно, бывает

Ссылка на сообщение
Поделиться на другие сайты
Спойлер

Способ выбора блоков? [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

 

Изменено пользователем doctorraz
Ссылка на сообщение
Поделиться на другие сайты
6 часов назад, doctorraz сказал:
6 часов назад, Robink сказал:

Я просто не пользовался continue, сначала не правильно понял как оно работает.

иногда удобно, бывает

Я бы сказал, что часто (а не иногда) бывает удобно.

Прерывание текущей итерации в цикле - весьма востребованная функция при обработке массивов.

Ссылка на сообщение
Поделиться на другие сайты

В этом случае можно было без continue, скобки двигать не захотел)))

Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Расскажите друзьям

    Нравится Официальный форум компании Нанософт? Расскажите друзьям!
×
×
  • Создать...