Задержка после перемещения микросервиса (с использованием процессов ZeroMQ, C, & Python) с 64-разрядного оборудования на 32-разрядное оборудование, но при номинальном использовании процессора - PullRequest
1 голос
/ 05 февраля 2020

У меня есть два процесса, записанные в C, которые устанавливают PUSH/PULL сокеты ZeroMQ и два потока в Python процессе, которые отражают сокеты PUSH/PULL. Примерно 80–300 легких сообщений (<30 байт) в секунду отправляются из процесса C в процесс Python, и 10–30 аналогичных сообщений из процесса Python в процесс C. </p>

Я запускал эти сервисы на 64-битных ARMv8 (на основе Ubuntu) и AMD64 (Ubuntu 18.04) без заметных задержек. Я попытался запустить точно такие же сервисы в 32-битной системе Linux и был шокирован, увидев сообщения, приходящие более чем через 30 секунд, даже после уничтожения сервисов C. При проверке использования процессора, он был довольно плоским 30-40% и, похоже, не шейкой bottle.

Настройки моего сокета ZeroMQ не менялись между системами, я установил LINGER на 0, я пробовал RCVTIMEO между 0 и 100 мс, и я пытался варьировать BACKLOG между 0 и 50, без разницы в любом случае. Я попытался использовать несколько потоков ввода-вывода и установить сходство потоков сокетов, также безрезультатно. Для сокетов PUSH я подключаю разъемы на tcp://localhost:##### и привязываю разъемы PULL к tcp://*:#####. Я также использовал ipc:///tmp/..., сообщения отправлялись и принимались, но задержка все еще существовала в 32-битной системе.

Я исследовал другие Python шаги между приемом сообщений, и они не кажется, занимает не более миллисекунды. Когда я определяю время socket.recv(0), оно достигает 0,02 секунды, даже если для этого сокета установлено значение RCVTIMEO.

Любые предположения, почему я вижу такое поведение на новой 32-битной платформе, а не на другие платформы? Возможно, я смотрю во всех неправильных местах?

Вот небольшой код, который поможет объяснить:

Соединение и метод класса _recv() примерно изображены ниже:

    def _connect(self):
        self.context = zmq.Context(4)
        self.sink = self.context.socket(zmq.PULL)
        self.sink.setsockopt(zmq.LINGER, 0)
        self.sink.setsockopt(zmq.RCVTIMEO, 100)
        self.sink.setsockopt(zmq.BACKLOG, 0)
        self.sink.bind("tcp://*:55755")

    def _recv(self):
        while True:
            msg = None
            try:
                msg = self.sink.recv(0)  # Use blocking or zmq.NOBLOCK, still appears to be slow
            except zmq.Error
                ... meaningful exception handle here

            # This last step, when timed usually takes less than a millisecond to process
            if msg:
                msg_dict = utils.bytestream_to_dict(msg)  # unpacking step (negligible)
                if msg_dict:
                    self.parser.parse(msg_dict)  # parser is a dict of callbacks also negligible

На стороне процесса C

    zmq_init (4);

    void *context = zmq_ctx_new ();

    /* Connect the Sender */
    void *vent = zmq_socket (context, ZMQ_PUSH);

    int timeo = 0;
    int timeo_ret = zmq_setsockopt(vent, ZMQ_SNDTIMEO, &timeo, sizeof(timeo));
    if (timeo_ret != 0)
        error("Failed to set ZMQ recv timeout because %s", zmq_strerror(errno));

    int linger = 100;
    int linger_ret = zmq_setsockopt(vent, ZMQ_LINGER, &linger, sizeof(linger));
    if (linger_ret != 0)
        error("Failed to set ZMQ linger because %s", zmq_strerror(errno));

    if (zmq_connect (vent, vent_port) == 0)
        info("Successfully initialized ZeroMQ ventilator on %s", vent_port);
    else {
        error("Failed to initialize %s ZeroMQ ventilator with error %s", sink_port, 
               zmq_strerror(errno));
        ret = 1;
    }

    ...

    /* When a message needs to be sent it's instantly hitting this where msg is a char* */
    ret = zmq_send(vent, msg, msg_len, ZMQ_NOBLOCK);

Вкл. docker на целевой 32-битной системе lstopo - -v --no-io

Machine (P#0 local=1019216KB total=1019216KB HardwareName="Freescale i.MX6 Quad/DualLite (Device Tree)" HardwareRevision=0000 HardwareSerial=0000000000000000 Backend=Linux LinuxCgroup=/docker/d2b0a3b3a5eedb7e10fc89fdee6e8493716a359597ac61350801cc302d79b8c0 OSName=Linux OSRelease=3.10.54-dey+g441c8d4 OSVersion="#1 SMP PREEMPT RT Tue Jan 28 12:11:37 CST 2020" HostName=db1docker Architecture=armv7l hwlocVersion=1.11.12 ProcessName=lstopo)
  Package L#0 (P#0 CPUModel="ARMv7 Processor rev 10 (v7l)" CPUImplementer=0x41 CPUArchitecture=7 CPUVariant=0x2 CPUPart=0xc09 CPURevision=10)
    Core L#0 (P#0)
      PU L#0 (P#0)
    Core L#1 (P#1)
      PU L#1 (P#1)
    Core L#2 (P#2)
      PU L#2 (P#2)
    Core L#3 (P#3)
      PU L#3 (P#3)
depth 0:        1 Machine (type #1)
 depth 1:       1 Package (type #3)
  depth 2:      4 Core (type #5)
   depth 3:     4 PU (type #6)

lstopo

РЕДАКТИРОВАТЬ:

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

1 Ответ

0 голосов
/ 05 февраля 2020

Q : примерно 80 - 300 легких (<30 байт) сообщений в секунду, отправляемых из процесса C в процесс Python, и 10-30 аналогичные сообщения от процесса Python к процессу C. </em>

a ) Нулевая информация об отправке любых сообщений от python до C (не об этом, содержащемся в опубликованном исходном коде, только C PUSH -e до python)

b ) 300 [Hz] <30 B полезные нагрузки - ничто, с точки зрения возможностей ZeroMQ </p>

c) python является, поскольку всегда (и почти наверняка таковым останется), в смысле чисто [SERIAL] любым количеством Thread -экземпляры, поэтому любому исполнению придется подождать, пока POSACK не получит владение GIL-блокировкой , заблокировав любую другую работу, таким образом воссоздав чисто [SERIAL] рабочую единицу- шаг за другим ... но при этом добавляются дополнительные затраты на рукопожатие GIL-блокировки.

d ), учитывая, что все процессы выполняются на одном и том же жестком диске Электронная платформа (см. tcp://localhost... указано), нет причин порождать столько, сколько (4 + 4) -IO-потоков (где python не может "использовать" их при чтении одним-единственным потоком за раз (slo-mo), учитывая, что не более, чем о 4-ядерных ядрах было сообщено выше lstopo выдержка:

Machine (995MB)
+Package L#0
 Core L#0 +PU L#0 (P#0)
 Core L#1 +PU L#1 (P#1)
 Core L#2 +PU L#2 (P#2)
 Core L#3 +PU L#3 (P#3)

e ) Параметры ISO-OSI-L2 / L3 имеют смысл настроить, но после того, как все более крупные источники задержки были сброшены.

f ) последний, но не менее важный: выполнить python pystone тест (как на исходной платформе, так и на целевой аппаратной платформе), чтобы увидеть фактическую относительную производительность i.MX6 -PCP-питание python, чтобы иметь возможность сравнивать яблоки с яблоками

Запуск Pystone на целевой машине приводит к: Эта машина оценивает в 10188,5 Pystones / второй и мой хост-компьютер - 274264 пиестона в секунду

, поэтому проблема с развертыванием на цели i.MX6 заключается не только в ее 3 2-битный O / S как таковой, но также 27x более медленная обработка переподписанных IO-потоков (больше потоков 4 + 4, чем 4-CPU-ядер) не улучшать поток сообщений.


Лучшее представление, обслуживаемое lstopo-no-graphics -.ascii

    ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
    │ Machine (31876MB)                                                                                                 │
    │                                                                                                                   │
    │ ┌────────────────────────────────────────────────────────────┐                      ┌───────────────────────────┐ │
    │ │ Package P#0                                                │  ├┤╶─┬─────┼┤╶───────┤ PCI 10ae:1F44             │ │
    │ │                                                            │      │               │                           │ │
    │ │ ┌────────────────────────────────────────────────────────┐ │      │               │ ┌────────────┐  ┌───────┐ │ │
    │ │ │ L3 (8192KB)                                            │ │      │               │ │ renderD128 │  │ card0 │ │ │
    │ │ └────────────────────────────────────────────────────────┘ │      │               │ └────────────┘  └───────┘ │ │
    │ │                                                            │      │               │                           │ │
    │ │ ┌──────────────────────────┐  ┌──────────────────────────┐ │      │               │ ┌────────────┐            │ │
    │ │ │ L2 (2048KB)              │  │ L2 (2048KB)              │ │      │               │ │ controlD64 │            │ │
    │ │ └──────────────────────────┘  └──────────────────────────┘ │      │               │ └────────────┘            │ │
    │ │                                                            │      │               └───────────────────────────┘ │
    │ │ ┌──────────────────────────┐  ┌──────────────────────────┐ │      │                                             │
    │ │ │ L1i (64KB)               │  │ L1i (64KB)               │ │      │               ┌───────────────┐             │
    │ │ └──────────────────────────┘  └──────────────────────────┘ │      ├─────┼┤╶───────┤ PCI 10bc:8268 │             │
    │ │                                                            │      │               │               │             │
    │ │ ┌────────────┐┌────────────┐  ┌────────────┐┌────────────┐ │      │               │ ┌────────┐    │             │
    │ │ │ L1d (16KB) ││ L1d (16KB) │  │ L1d (16KB) ││ L1d (16KB) │ │      │               │ │ enp2s0 │    │             │
    │ │ └────────────┘└────────────┘  └────────────┘└────────────┘ │      │               │ └────────┘    │             │
    │ │                                                            │      │               └───────────────┘             │
    │ │ ┌────────────┐┌────────────┐  ┌────────────┐┌────────────┐ │      │                                             │
    │ │ │ Core P#0   ││ Core P#1   │  │ Core P#2   ││ Core P#3   │ │      │     ┌──────────────────┐                    │
    │ │ │            ││            │  │            ││            │ │      ├─────┤ PCI 1002:4790    │                    │
    │ │ │ ┌────────┐ ││ ┌────────┐ │  │ ┌────────┐ ││ ┌────────┐ │ │      │     │                  │                    │
    │ │ │ │ PU P#0 │ ││ │ PU P#1 │ │  │ │ PU P#2 │ ││ │ PU P#3 │ │ │      │     │ ┌─────┐  ┌─────┐ │                    │
    │ │ │ └────────┘ ││ └────────┘ │  │ └────────┘ ││ └────────┘ │ │      │     │ │ sr0 │  │ sda │ │                    │
    │ │ └────────────┘└────────────┘  └────────────┘└────────────┘ │      │     │ └─────┘  └─────┘ │                    │
    │ └────────────────────────────────────────────────────────────┘      │     └──────────────────┘                    │
    │                                                                     │                                             │
    │                                                                     │     ┌───────────────┐                       │
    │                                                                     └─────┤ PCI 1002:479c │                       │
    │                                                                           └───────────────┘                       │
    └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
...