Несколько очередей в MSMQ (падение производительности)

Почему производительность MSMQ падает (примерно на треть), когда я использую 10 очередей вместо 1?

Короче говоря, производительность MSMQ резко падает, когда я использую более 1 очереди в многопоточном приложении (получение из каждой очереди в другом потоке).

Это похоже на то, что классы MSMQ в .NET имеют общий ресурс, который сокращается при увеличении числа очередей. Кстати, я использую Windows 7 для этих тестов с Visual Studio 2010.

Примечание. У меня была 1 очередь для связи между двумя приложениями. Мне нужно использовать только восстанавливаемый режим. Он работал нормально, пока не достиг стены со скоростью 100-150 сообщений в секунду. Затем я подумал, что могу увеличить вычислительную мощность, увеличив количество очередей до 10 и обрабатывая их параллельно. Но когда я это сделал, время приема увеличилось почти в 3 раза! :О

Я писал свои приложения на C#. Я инициализирую свои потоки чтения следующим образом:

for (int i = 101; i <= 110; i++)
{
    var t = new Task<Tuple<TimeSpan, int, int, int>>(SingleQueueReceiver, i, TaskCreationOptions.LongRunning);
    tasks.Add(t);
}
foreach (var t in tasks) t.Start();

И имена моих очередей от buffer101 до buffer110, которые я уже создал. Они не являются транзакционными. Моя функция задачи приемника (поток) такова:

static Tuple<TimeSpan, int, int, int> SingleQueueReceiver(object o)
{
    var qID = (int)o;

    TimeSpan SingleQueueReceiver_Elapsed = TimeSpan.FromMilliseconds(0);
    int SingleQueueReceiver_Count = 0;
    var watch = new Stopwatch();
    watch.Start();

    using (var q = new MessageQueue(string.Format(@".\private$\buffer{0}", qID), QueueAccessMode.Receive))
    {
        q.UseJournalQueue = false;
        var @continue = true;
        var sleep = TimeSpan.FromMilliseconds(1);

        while (true)
        {
            if (!@continue)
            {
                watch.Stop();
                SingleQueueReceiver_Elapsed = watch.Elapsed.Subtract(sleep);

                return Tuple.Create(SingleQueueReceiver_Elapsed, SingleQueueReceiver_Count, qID, 2);
            }

            try
            {
                var m = q.Receive(sleep);

                SingleQueueReceiver_Count++;
            }
            catch (MessageQueueException mqe)
            {
                if (mqe.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout) @continue = false;
            }
        }
    }
}

person Kaveh Shahbazian    schedule 01.12.2012    source источник
comment
Пробовали ли вы использовать await-async и Parallel-TPL?   -  person Kiquenet    schedule 10.03.2015
comment
Нет, мои проблемы были решены мгновенно с помощью RabbitMQ.   -  person Kaveh Shahbazian    schedule 10.03.2015
comment
любой образец с использованием RabbitMQ и Task (SingleQueueReceiver)?   -  person Kiquenet    schedule 11.03.2015
comment
Я начал с [codethinked.com/using-rabbitmq -with-c-and-net//] и [dotnetcodr.com/2014/05/08/ и построил некоторые абстракции, чтобы упростить задачу, и у меня это отлично сработало. Позже я наткнулся на [easynetq.com//], но никогда не использовал его в рабочем коде - пока.   -  person Kaveh Shahbazian    schedule 11.03.2015


Ответы (1)


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

Пробовали ли вы масштабироваться до 10 очередей и 10 однопоточных слушателей?

Если вы опубликуете свой код, мы, надеюсь, увидим, что происходит.

person tom redfern    schedule 01.12.2012
comment
Спасибо, Каве, глядя на код, я вижу, что вы создаете новые потоки внутри одного процесса. Я имел в виду, что нужно иметь по одному потоку на процесс и размещать больше процессов. - person tom redfern; 03.12.2012
comment
Под процессом вы подразумеваете, что я должен использовать это в отдельных (консольных) приложениях? - person Kaveh Shahbazian; 03.12.2012