Загрузка ЦП на 100% с издателем ZeroMQ (C) - PullRequest
1 голос
/ 25 октября 2019

Я пишу ZeroMQ Publisher на C, который отправляет одно сообщение в цикле while. Я установил его верхний водяной знак как "20":

int sndhwm = 20;
size_t sndhwm_size = sizeof(sndhwm);
int rc = zmq_setsockopt(publisher, ZMQ_SNDHWM, &sndhwm, sndhwm_size);

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

int sndhwm2;
size_t sndhwm_size2 = sizeof(sndhwm2);
rc = zmq_getsockopt(publisher, ZMQ_SNDHWM, &sndhwm2, &sndhwm_size2);
printf("sndhwm: %i\n",sndhwm2);

Правильно печатает результат.

Однако, когда я запускаю программу, CPUиспользование почти всегда на 100%.

enter image description here

Я заметил, что этого не происходит, если после каждого send я выполняю sleep(1),а затем загрузка процессора довольно близка к 0%.

В чем здесь может быть проблема? Почему ядро ​​процессора на 100%? Это связано с установленным водяным знаком?

edit: Я использую libzmq3-dev версии 4.2.5.

edit2: Мои извиненияЯ почему-то ошибся с утечкой памяти при использовании ядра процессора. Я соответственно отредактировал вопрос.

Это воспроизводимый пример:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "zhelpers.h"


int main(int argc, char *argv []){

    void *context = zmq_ctx_new();
    void *publisher = zmq_socket(context, ZMQ_PUB);

    char buffer[50];
    snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:5000");

    int sndhwm = 20;
    size_t sndhwm_size = sizeof(sndhwm);
    int rc = zmq_setsockopt(publisher, ZMQ_SNDHWM, &sndhwm, sndhwm_size);

    rc = zmq_bind(publisher, buffer);

    int sndhwm2;
    size_t sndhwm_size2 = sizeof(sndhwm2);
    rc = zmq_getsockopt(publisher, ZMQ_SNDHWM, &sndhwm2, &sndhwm_size2); 
    assert(rc == 0);

    while (1){
        rc = s_send(publisher, "hello"); 
        //sleep(1);
    }

    zmq_close(publisher);
    zmq_ctx_destroy(context);

    return 0;
}

Ответы [ 2 ]

1 голос
/ 28 октября 2019

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

Вам нужно.

  • Передать флаг ZMQ_DONTWAIT на zmq_send
  • Проверить zmq_sendвозвращаемое значение для ошибки (-1)
  • Если вы получили ошибку, проверьте ошибку (для определения между нажатием HWM и реальной ошибкой)

Кстати, я не уверен, что s_sendвернется, но, вероятно, лучше использовать функции, представленные в libzmq или cppzmq.

1 голос
/ 25 октября 2019

Подобный жесткий цикл обычно приводит к 100% -ной загрузке процессора. Почему вы думаете, что это не должно?

Если вы добавите sleep(), ваш процесс будет переходить в спящий режим на 1 секунду на каждой итерации. Это очень длительное время для ЦП, и загрузка ЦП обычно составляет 0%, если не выполняются другие интенсивные процессы.

Когда сокет издателя достигнет максимальной отметки, я думаю, что он просто отбросит любойновые сообщения. По сути, это неоперация (без операции), которая создает замкнутый цикл и приводит к 100% использованию ЦП.

Если вы не видите 100% использования ЦП, когда вы не устанавливаете максимальная отметка, я думаю, что издатель будет продолжать буферизовать новые сообщения, особенно если подписчики не подключены. Это связано с выделением памяти, что является относительно медленной операцией. Это может снизить загрузку ЦП, поскольку ЦП должен ждать в памяти, переключаться на диск и т. Д.

...