Влияние на производительность использования средства опроса netmq

В следующем коде я отправляю и получаю 100 000 сообщений, используя сокеты netmq push/pull. Сначала я попытался сделать простой блокирующий вызов, используя ReceiveFrameString (метод ReceiveSimple) в моем сокете pull, затем я попытался использовать опросник, чтобы сделать то же самое (метод ReceiveWithPoller).

Использование опросника существенно влияет на время, необходимое для отправки/получения сообщений. Я попытался выяснить, почему самостоятельно, используя dotTrace, и обнаружил, что много времени уходит на ожидание выполнения Socket.Select.

Может ли кто-нибудь подтвердить или объяснить эту разницу?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NetMQ;
using NetMQ.Sockets;

namespace PushPull
{
    class Program
    {
        static int messageReceived = 0;

        const int sampleCount = 100 * 1000;

        static void Main(string[] args)
        {
            // Create psu socket
            PushSocket pushSocket = new PushSocket();
            pushSocket.Bind("tcp://localhost:5555");

            // Create pull socket
            PullSocket pullSocket = new PullSocket();
            pullSocket.Connect("tcp://localhost:5555");

            Console.WriteLine("Ready...press any key to start");
            Console.ReadKey();
            Console.WriteLine();

            // Start sending
            Task.Run(() =>
            {
                for (int i = 0; i < sampleCount; i++)
                {
                    pushSocket.SendFrame(Encoding.UTF8.GetBytes("ping"));
                }
            });

            Stopwatch sw = Stopwatch.StartNew();

            //ReceiveSimple(pullSocket);

            ReceiveWithPoller(pullSocket);

            // Display result.
            sw.Stop();
            Console.WriteLine();
            Console.WriteLine("{0} message exchanged in {1} msecs", sampleCount, sw.Elapsed.TotalMilliseconds);
        }

        private static void ReceiveSimple(PullSocket pullSocket)
        {
            messageReceived = 0;
            do
            {
                pullSocket.ReceiveFrameString();
            } while (!HandleMessage());
        }

        private static void ReceiveWithPoller(PullSocket pullSocket)
        {
            NetMQPoller poller = new NetMQPoller();
            poller.Add(pullSocket);
            pullSocket.ReceiveReady += (sender, eventArgs) =>
            {
                if (HandleMessage())
                {
                    poller.Stop();
                }
            };
            poller.Run();
        }

        private static bool HandleMessage()
        {
            messageReceived++;

            if (messageReceived % 10000 == 0)
            {
                Console.WriteLine("10k");
            }

            return messageReceived == sampleCount;
        }
    }
}

person sebferry    schedule 05.05.2016    source источник
comment
кстати у вас в примере баг, в обработчике события ReceiveReady вы никогда не получаете сообщение из сокета.   -  person somdoron    schedule 05.05.2016


Ответы (1)


Поллер дорог, когда вы обрабатываете много сообщений, но для этого есть очень простое решение.

Получить все сообщения в очереди, когда вы получите готовое событие, вы можете сделать это с помощью методов Try *, в вашем примере так:

 pullSocket.ReceiveReady += (sender, eventArgs) =>
 {
    string message;
    while (pullSocket.TryReceiveFrameString(out message) 
    {
        if (HandleMessage())
        {
            poller.Stop();
        }
    }
 };
person somdoron    schedule 05.05.2016
comment
Я добавил это в документы NetMQ: github.com/zeromq/ netmq/blob/master/docs/poller.md#performance - person somdoron; 06.05.2016