Большое время вычислений

2

Здесь была ссылка на предыдущий вопрос, который привел меня к этому. С# Вложенная оптимизация цикла foreach

По-прежнему существует большое время вычисления, и я не уверен, в чем причина.

object foo;
List<string> StringList = new List<string>(); // Populated by previous code
Dictionary<string, Type> assemblyTypes = RandomAssembly.GetTypes().ToDictionary(t => t.Name, t => t);

  foreach (String name in StringList)
  {                     
    if (assemblyTypes.ContainsKey(name))
    {
      // Create an instance of the matching class and add it
      // to the appropriate lists.
      Type at = assemblyTypes[name];
      foo = Activator.CreateInstance(at);       
      ArbitraryList1.Add(foo);
    }
  }    
  • 0
    ANTZ Profiler довольно хорошо справляется с подобными проблемами, и у них есть бесплатная пробная версия.
  • 3
    Activator.CreateInstance работает довольно медленно.
Показать ещё 5 комментариев
Теги:
wpf
foreach

3 ответа

3
Лучший ответ

Если время вычисления заметно медленное, я предполагаю, что вы часто вызываете этот код, и вы создаете множество объектов, о которых вы мало что знаете во время компиляции.

Вместо того, чтобы держать классы в Dictionary<string, type> и вызывать CreateInstance, вы хотите сохранить словарь своих конструкторов Dictionary<string, ConstructorInfo>, чтобы вы могли напрямую ихзывать, не задумываясь при каждом его отражении.

Таким образом вы можете просто вызвать AssemblyConstructors [Name].Invoke(), чтобы создать новый экземпляр класса.

Таким образом вам нужно только один раз использовать отражение, чтобы найти конструкторы.

// keep a dictionary of constructors (instead of the types)
var Constructors = new Dictionary<string, ConstructorInfo>();            

// add this class to this dictionary
Type t = typeof(SomeClass);            
string name = t.Name;
Constructors[name] = t.GetConstructors()[0]; // use reflection only once here, afterwards we reuse the reflected info

// new up an instance 
var o = Constructors[name].Invoke(new object[] {}); 

Я думаю, что первый конструктор будет без параметров. Попробуйте что-то вроде t.GetConstructors().Where(x => x.GetParameters().Count() == 0).First(); Это самый быстрый способ, который я знаю, потому что, по-видимому, вы не можете получить делегата для конструктора.

Если вы пишете классы, которые вы создаете сами, у вас может быть общий базовый класс или интерфейс с методом, который создает его, таким образом вы можете сохранить делегат этого конструктора, что еще быстрее.

В этом сообщении также есть некоторые интересные идеи об этом, которые еще больше оптимизируют много. Если вы хотите сделать это быстро, вы можете. Почти так же быстро, как просто вызов new KnownClass()

Удачи,

ГДж

  • 0
    хорошая вещь. Особенно эта ссылка на блог Хайбо Ло.
1

Резюме: существенно неограниченный цикл с одной из самых медленных функций в структуре, называемой каждой итерацией, будет медленным.

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

  • 0
    Самая медленная функция не вызывается в каждом цикле. Он окружен проверкой if. Предположительно, есть намного больше типов, чем есть типы, которые они хотят активировать. Я бы больше беспокоился об итерации по множеству несоответствующих типов.
0

Используйте Dictionary.TryGetValue, чтобы искать ключ "имя" один раз вместо двух. Это всего лишь маленький наконечник, поскольку я уверен, что отражение является узким местом.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню