mojo using 100% CPU

43 views
Skip to first unread message

Jeremy

unread,
Feb 24, 2017, 5:31:48 PM2/24/17
to mojol...@googlegroups.com

All,

I was doing some stress testing for an embedded app that sends lots of websocket messages, and I can't understand some odd behaviour. Basically mojo stalls using 100% CPU for many seconds. Doing the following (to simulate heavy load):

         for (1..10000) {
           $sc->{websocket}->send({text => $payload});
         }

Will send 10000 messages to the client (they all arrive) but then mojo stalls using 100% CPU for 19 seconds or so. Running nytprof, I get this:

10000 1 1 19.2s 19.2s Mojo::EventEmitter::unsubscribe

50 10000 3.89ms if ($cb) {
51 10000 19.1s $self->{events}{$name} = [grep { $cb ne $_ } @{$self->{events}{$name}}];
52 10000 9.66ms delete $self->{events}{$name} unless @{$self->{events}{$name}};

Looking at the above code it seems to suggest that a callback is being used, but I am not sure where/how it was created? I do use the following paradigm in my code, could this be the cause of the problem?

my $id = Mojo::IOLoop->client({address => '127.0.0.1', port => 5001} => sub {
  my ($loop, $err, $stream) = @_;
  ...
  $stream->on(read => sub {
    my ($stream, $bytes) = @_;
    # Process input 
    ...
    [call a function that would send these 10000 messages to the websocket]
  });
});

Thanks,


sri

unread,
Feb 24, 2017, 5:40:08 PM2/24/17
to Mojolicious
         for (1..10000) {
           $sc->{websocket}->send({text => $payload});
         }

This is fundamentally flawed code. All your're doing here is building 10000 websocket
frames and appending them one by one to a write buffer. No actual I/O is performed here and
lots of time wasted that could be spent doingother stuff concurrently.

--
sebastian

jez_...@hotmail.com

unread,
Feb 25, 2017, 5:06:14 AM2/25/17
to Mojolicious

Hi,

Thanks for the reply. The above code is to highlight the 'problem', but I certainly accept that I could be doing something wrong and this isn't a problem at all:)

Flipping the question around slightly, if I know I've got 10000 messages sitting in an event queue that needs to be sent to a websocket, how should I do it with out causing this CPU spike? Should I call one_tick or something similar?

To give a little more information, I'm using an incoming socket to notify me that there is (at least one) event to be handled in a thread safe event queue, then in my event handler I have something like this (pseudo code):

sub EventHandler {
  while ($eventQueue->HasMessages) {
    my ($messageCode,$messageObject) = $eventQueue->GetMessage();
      if ($messageCode == 12) {
         #in reality we would have multiple websockets here
         $websocket->send({text => $messageObject});
      }
  }
}


Regards,


Reply all
Reply to author
Forward
0 new messages