2013-05-09 2 views
0

Чтобы проиллюстрировать эту проблему, скомпилируйте проект C# со ссылкой на Runtime Microsoft Scripting Runtime и код ниже. Запустите один экземпляр результирующего исполняемого файла. На моей 12-ядерной машине цикл чтения последовательно занимает около 180 мс. Запуск другого экземпляра исполняемого файла замедляет это, примерно на 100 мс на дополнительный исполняемый файл.Scripting.Dictionary Performance страдает в нескольких процессах

Любые идеи, что происходит? И любые решения, кроме переключения на другую реализацию словаря?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication4 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      System.Diagnostics.Stopwatch stp = new System.Diagnostics.Stopwatch(); 
      var dict = (Scripting.IDictionary)(new Scripting.Dictionary()); 
      stp.Start(); 
      for (int i = 1; i < 1000; ++i) 
      { 
       Object s = i.ToString(); 
       dict.Add(ref s, ref s); 
      } 
      Console.WriteLine("After Add {0}", stp.ElapsedMilliseconds); 
      object q = null; 
      for (int j = 0; j < 1000; ++j) 
      { 
       long old = stp.ElapsedMilliseconds; 
       for (int i = 1; i < 10000; ++i) 
       { 
        q = null; 
        object s = i.ToString() as object; 
        q = dict.get_Item(ref s); 
       } 
       long newval = stp.ElapsedMilliseconds; 
       Console.WriteLine("After Retrieve {0}", newval - old); 
      } 

     } 
    } 
} 
+1

Прокрутка тысячи строк текста через консоль, в то время как временной код - очень плохая идея. –

+2

Я написал 'Scripting.Dictionary' в 1997 году.Я понятия не имею, в чем причина вашей проблемы, но мне было бы интересно узнать. Как бы то ни было, я могу заверить вас, что это вряд ли когда-либо будет исправлено. –

ответ

0

Эрик, вы будете рады услышать, что проблема не является специфической для Scripting.Dictionary, а с моделью потоковой. Можно прочитать о влиянии смешанных резьбовых соединений на MSDN, однако неожиданностью (для меня) является влияние вне процесса.

Я смог создать свой собственный COM-объект с помощью одного метода, как описано ниже, заменив вызовы Scripting.Dictionary в приведенном выше примере. Затем я могу переключиться между файлами Threads и «Both» в файле Test.rgs, перестроить и подтвердить, что влияние межсетевого процесса разрешено в объекте с поддержкой MTA.

Кроме того, прикрепление отладчика и приостановка процесса, а затем использование procexp (из Microsoft SysInternals), можно увидеть, что стек вызовов загорается в ядро, где я предполагаю, что для сортировки COM управляется одна очередь, вызывая шею бутылки в разных процессах.

Хуже того, это замедление происходит также при сортировке вызовов на разные объекты, которые наблюдаются при запуске одного приложения, вызывающего в Scripting.Dictionary, несколько других, вызывающих DoNothing(), и наблюдение за их замедлением.

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

Я полагаю, что до сих пор остается нерешенным вопрос о межпроцессном воздействии комминирования COM. Рекомендация должна состоять в том, чтобы попытаться избежать нарезки квартир в многопроцессорной среде, если у кого-то нет лучшего ответа ...?

Создание тестовой COM объекта

  • Создать новый проект в Visual Studio, используя C++ ATL Template (я использую VS 2008).
  • Выберите тип DLL сервера.
  • Щелкните правой кнопкой мыши проект, добавьте класс ... -> ATL Simple Object.
  • Дайте короткое имя, например. «Тест», убедитесь, что выбрана резьба на резьбе.
  • Из представления класса щелкните правой кнопкой мыши интерфейс (ITest) и Add Method ...
  • Назовите этот метод, например. «DoNothing», и оставьте параметры по умолчанию.
  • Проверьте, что реализация метода пуста, и Build.

Теперь можно добавить ссылку на COM из тестового приложения и вызвать метод DoNothing().

+1

Спасибо за обновление; рад, что ты это понял. Кстати, был один выпуск Scripting.Dictionary, где он был неправильно обозначен как Both, а не Apartment. Виноват. Вы можете прочитать забавную историю здесь: http://blogs.msdn.com/b/ericlippert/archive/2003/09/19/53054.aspx –

Смежные вопросы