Recent

Author Topic: Lazarus and MQTT: Publish function causes CPU usage to go up.  (Read 4608 times)

Awesome Programmer

  • Sr. Member
  • ****
  • Posts: 451
  • Programming is FUN only when it works :)
    • Cool Technology
Lazarus and MQTT: Publish function causes CPU usage to go up.
« on: February 07, 2018, 04:49:27 pm »
 :(
I am using and testing MQTT protocol on my Lazarus project. My program basically sends out or publishes 15 to 20 messages one after another every 5 seconds through MQTT broker. At the same time, my CPU usages goes up to 25% causing my whole system to freeze for about second or two. At which point, I have no control over anything on the screen. For the life of me, I can't seem to work around this issue or fix it somehow. If anyone can give me hints or clues, I would appreciate it. I have included the code that publishes MQTT messages.

Code: Pascal  [Select][+][-]
  1. procedure TWebFrm.Timer1Timer(Sender:TObject);
  2. var
  3.   I:Integer;
  4.   tmpstr,ValueStr:string;
  5. begin
  6.   Timer1.Enabled:=false;
  7.  
  8.   if MQTTClient2.isConnected=false then exit;
  9.  
  10.   for I:=0 to SignalList.Count-1 do
  11.   begin
  12.        if (TSignal(SignalList.Items[I]).f.WebEnabled=true) then
  13.        begin
  14.             tmpstr:=TSignal(SignalList.Items[I]).f.TagName;
  15.  
  16.             if (TSignal(SignalList.Items[I]).GetValueStr = 'OFF') then
  17.                ValueStr:='0'
  18.             else if (TSignal(SignalList.Items[I]).GetValueStr='ON') then
  19.                ValueStr:='1'
  20.             else
  21.                ValueStr:= inttostr(round(TSignal(SignalList.Items[I]).AsPercent));
  22.  
  23.             MQTTClient2.Publish('sensor/status/'+tmpstr, ValueStr, false);    //<<<<===== This is where my program publishes sensor information through MQTT broker.
  24.        end;
  25.   end;
  26.  
  27.   Timer1.Enabled:=true;
  28. end;
  29.  

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Lazarus and MQTT: Publish function causes CPU usage to go up.
« Reply #1 on: February 07, 2018, 07:02:41 pm »
Whole system freeze usually means, that very high priority thread (possibly driver one) is being executed, cuz even 50% CPU usage shouldn't freeze your system.

P.S. It was surprise for me, that such minor problem, as uninitialized local variable, can cause video driver to freeze whole system - via drawing lines with extremely wide pens.
« Last Edit: February 07, 2018, 07:10:10 pm by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

Cyrax

  • Hero Member
  • *****
  • Posts: 836
Re: Lazarus and MQTT: Publish function causes CPU usage to go up.
« Reply #2 on: February 07, 2018, 08:02:13 pm »
:(
I am using and testing MQTT protocol on my Lazarus project. My program basically sends out or publishes 15 to 20 messages one after another every 5 seconds through MQTT broker. At the same time, my CPU usages goes up to 25% causing my whole system to freeze for about second or two. At which point, I have no control over anything on the screen. For the life of me, I can't seem to work around this issue or fix it somehow. If anyone can give me hints or clues, I would appreciate it. I have included the code that publishes MQTT messages.

Code: Pascal  [Select][+][-]
  1. procedure TWebFrm.Timer1Timer(Sender:TObject);
  2. var
  3.   I:Integer;
  4.   tmpstr,ValueStr:string;
  5. begin
  6.   Timer1.Enabled:=false;
  7.  
  8.   if MQTTClient2.isConnected=false then exit;
  9.  
  10.   for I:=0 to SignalList.Count-1 do
  11.   begin
  12.        if (TSignal(SignalList.Items[I]).f.WebEnabled=true) then
  13.        begin
  14.             tmpstr:=TSignal(SignalList.Items[I]).f.TagName;
  15.  
  16.             if (TSignal(SignalList.Items[I]).GetValueStr = 'OFF') then
  17.                ValueStr:='0'
  18.             else if (TSignal(SignalList.Items[I]).GetValueStr='ON') then
  19.                ValueStr:='1'
  20.             else
  21.                ValueStr:= inttostr(round(TSignal(SignalList.Items[I]).AsPercent));
  22.  
  23.             MQTTClient2.Publish('sensor/status/'+tmpstr, ValueStr, false);    //<<<<===== This is where my program publishes sensor information through MQTT broker.
  24.        end;
  25.   end;
  26.  
  27.   Timer1.Enabled:=true;
  28. end;
  29.  

Change your code to use threading with TThread class.

Awesome Programmer

  • Sr. Member
  • ****
  • Posts: 451
  • Programming is FUN only when it works :)
    • Cool Technology
Re: Lazarus and MQTT: Publish function causes CPU usage to go up.
« Reply #3 on: February 07, 2018, 08:18:30 pm »
Oh i did that as well and it is acting exactly the same way... That doesn't make sense to me either. I thought when you run your code within a thread, your program will have enough time and resources to do its own thing, but not in this I guess.


Awesome Programmer

  • Sr. Member
  • ****
  • Posts: 451
  • Programming is FUN only when it works :)
    • Cool Technology
Re: Lazarus and MQTT: Publish function causes CPU usage to go up.
« Reply #4 on: February 07, 2018, 08:38:58 pm »
:(
I am using and testing MQTT protocol on my Lazarus project. My program basically sends out or publishes 15 to 20 messages one after another every 5 seconds through MQTT broker. At the same time, my CPU usages goes up to 25% causing my whole system to freeze for about second or two. At which point, I have no control over anything on the screen. For the life of me, I can't seem to work around this issue or fix it somehow. If anyone can give me hints or clues, I would appreciate it. I have included the code that publishes MQTT messages.

Code: Pascal  [Select][+][-]
  1. procedure TWebFrm.Timer1Timer(Sender:TObject);
  2. var
  3.   I:Integer;
  4.   tmpstr,ValueStr:string;
  5. begin
  6.   Timer1.Enabled:=false;
  7.  
  8.   if MQTTClient2.isConnected=false then exit;
  9.  
  10.   for I:=0 to SignalList.Count-1 do
  11.   begin
  12.        if (TSignal(SignalList.Items[I]).f.WebEnabled=true) then
  13.        begin
  14.             tmpstr:=TSignal(SignalList.Items[I]).f.TagName;
  15.  
  16.             if (TSignal(SignalList.Items[I]).GetValueStr = 'OFF') then
  17.                ValueStr:='0'
  18.             else if (TSignal(SignalList.Items[I]).GetValueStr='ON') then
  19.                ValueStr:='1'
  20.             else
  21.                ValueStr:= inttostr(round(TSignal(SignalList.Items[I]).AsPercent));
  22.  
  23.             MQTTClient2.Publish('sensor/status/'+tmpstr, ValueStr, false);    //<<<<===== This is where my program publishes sensor information through MQTT broker.
  24.  
  25.             sleep(1);
  26.        end;
  27.   end;
  28.  
  29.   Timer1.Enabled:=true;
  30. end;
  31.  

OMG... I just added sleep(1) right after publish procedure just like someone suggested on another website. He said, even one micro second is good enough... So, I just added one millisecond. This actually made big difference. Yes, my cpu at times goes up but only around 3 to 5 and then back down. Plus, my program is not freezing anymore...

Thank you fellow programmers for your suggestions and answers. If you still have more ideas or hints, please feel free to post your message in this thread. Thank you.

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Re: Lazarus and MQTT: Publish function causes CPU usage to go up.
« Reply #5 on: February 08, 2018, 03:31:18 am »
I just added sleep(1) right after publish procedure just like someone suggested on another website. He said, even one micro second is good enough... So, I just added one millisecond. This actually made big difference. Yes, my cpu at times goes up but only around 3 to 5 and then back down. Plus, my program is not freezing anymore...
Waiting for a network event blocks your thread. Having it in a loop makes it even worse. If that code is in your main application thread then gui message loop is blocked so your application form is not responding for a while. Using Application.ProcessMessages instead of Sleep(1) is better in such case. However, as already suggested it is much better if you put that load into separate thread to avoid not responding status in your application at all (but you have to sync with your thread which is not for a newbie). Sleep(xxx) is good to use in a thread.

Btw, 25% is probably because you have 4 cores cpu and the core running your code goes to 100% (100/4=25).
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Re: Lazarus and MQTT: Publish function causes CPU usage to go up.
« Reply #6 on: February 09, 2018, 12:24:23 pm »
I still use the ICS socket code via MESSAGE events, I don't use blocking ..
I am not aware of ICS internals, but if it doesn't automatically create and use some separate communication thread, communication will run in your main application thread. In that case it doesn't matter if you use some component with events or not - main application thread will be blocked with communication. That would not happen only if ICS uses separate thread.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Lazarus and MQTT: Publish function causes CPU usage to go up.
« Reply #7 on: February 09, 2018, 12:35:41 pm »
I still use the ICS socket code via MESSAGE events, I don't use blocking ..
I am not aware of ICS internals, but if it doesn't automatically create and use some separate communication thread, communication will run in your main application thread. In that case it doesn't matter if you use some component with events or not - main application thread will be blocked with communication. That would not happen only if ICS uses separate thread.
ICS uses the windows asynchronous sockets not threads and no it does not lock the application while sending and receiving.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

promisetom

  • New Member
  • *
  • Posts: 11
Re: Lazarus and MQTT: Publish function causes CPU usage to go up.
« Reply #8 on: April 28, 2021, 07:48:31 am »
I still use the ICS socket code via MESSAGE events, I don't use blocking ..

 I was able to get enough of it to work with Fpc so I was able to port my FTP, Web Browser code over
to laz.
 Message events allows me to smoothly operation the app without using secondary threads so I don't have
restrictive use of the LCL.


I know this is an old post but do you have an ics unit that you could share using lazarus.
I use an MQTT client which uses ics and would love to use that in my Lazarus designs.
Thanks
Tom

 

TinyPortal © 2005-2018