imll
imll

Reputation: 341

CPU usage at 100% with ZeroMQ publisher (C)

I'm writing a ZeroMQ Publisher in C that sends a single message in a while loop. I set its high watermark as "20":

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

I wrote this piece of code before the bind. After the bind, I print the value of the watermark, just to make sure it was set:

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

It prints the result correctly.

However, when I run the program, CPU usage is almost always at 100%.

enter image description here

I noticed this does not happen if, after every send, I execute a sleep(1), and then CPU usage is pretty close to 0%.

What could be the problem here? Why is the CPU core at 100%? Is it related to the set watermark?

edit: I'm using libzmq3-dev version 4.2.5.

edit2: My apologies, for some reason I mistook the memory leak with the CPU core usage. I edited the question accordingly.

This is the reproducible example:

#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;
}

Upvotes: 1

Views: 1140

Answers (2)

jamesdillonharvey
jamesdillonharvey

Reputation: 1042

To control the behaviour you can tell the pub socket to inform you if the send operation failed due to a full buffer. That way you can decide when to sleep your loop.

You need to.

  • Pass the flag ZMQ_DONTWAIT on zmq_send
  • Check zmq_send return value for failure (-1)
  • If you get failure check the errno (to determine between hitting HWM and a real error)

BTW I am not sure what s_send will return is but it's probably best to use the functions provided in libzmq or cppzmq.

Upvotes: 1

rveerd
rveerd

Reputation: 4006

A tight loop like that will usually lead to 100% CPU. Why do you think it shouldn't?

If you add the sleep() your process will go to sleep for 1 second on each iteration. This is a very long time for a CPU and CPU usage will usually go to 0%, if no other intensive processes are running.

When the publisher socket reaches the high water mark, I think it will just drop any new messages. This is basically a no-op (no operation), which gives a tight loop and this leads to 100% CPU usage.

If you do not see 100% CPU usage when you do not set the high water mark, I think the publisher will keep buffering new messages, especially if no subscribers are connected. This involves memory allocation, which is a relatively slow operation. This could give a lower a CPU usage as the CPU has to wait on memory, swapping to disk, etc..

Upvotes: 1

Related Questions