Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2021-10

Command line program - CPU overused - do I need profiling?

3 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bo Berglund

Failed to post via Gmane so trying direct emailing instead:

I need to figure out why my program uses 10% CPU when it is essentially idle, waiting for a client connect via TCP or for the time for a new task start to arrive. It is a command line program running as a service on Linux (Raspberry Pi4). Developed on the RPi4 with Lazarus 2.0.12 and FPC 3.2.0

This is the main loop in the program following creatrion of the handler objects (which are idle):

      While not (bSTerm or bSInt or bsHup) do
      begin
        //Eternal loop to wait for system messages
        CheckSynchronize(5); //Timeout here instead of using sleep
        if CheckRestartReq then
        begin
          Debug_Writeln('Restart timeout reached - exiting');
          FLogServ.StdLog('Restart timeout reached - exiting');
          break;
        end;
      end;

The while loop breaks on system messages sent by systemd when running as a service or from the keyboard (Ctrl-C) if started in a terminal.

Can this loop by itself cause the 10% CPU usage?
The checksynchronize() is needed because some of the handler objects spawn communications threads that need this in order to transfer their data to the main object.

I have looked for a way to "profile" the program and found LazProfiler, which has a forum support thread in which I posted questions about profiling my problem:

https://forum.lazarus.freepascal.org/index.php/topic,38983.msg420564.html#msg420564

But it looks like an uphill task to do the profiling...

Bo Berglund Developer in Sweden

Reply by email

Unknown author
to Bo Berglund
Bo Berglund wrote
This is the main loop in the program following creatrion of the handler objects (which are idle):
          QuitSignal:=false;
While not (bSTerm or bSInt or bsHup) do
          While not QuitSignal do
Show quoted text 9 lines
begin //Eternal loop to wait for system messages CheckSynchronize(5); //Timeout here instead of using sleep if CheckRestartReq then begin Debug_Writeln('Restart timeout reached - exiting'); FLogServ.StdLog('Restart timeout reached - exiting'); break; end;
            QuitSignal:=(bSTerm or bSInt or bSHup);
end;

i doubt it will make a difference but what if you adjust the code as shown above? this puts the while test to check only one item instead of three...

The while loop breaks on system messages sent by systemd when running as a service or from the keyboard (Ctrl-C) if started in a terminal. Can this loop by itself cause the 10% CPU usage?

possibly... it depends on what CheckSynchronize and CheckRestartReq are doing...

i don't know of any profilers for command line or service apps... nothing other than logging with fine timestamps and analyzing the log... this is when i add debug logging with entry and exit messages logged for each routine and loop... this allows me to see the code flow and to monitor the time taken in each section...

NOTE: No off-list assistance is given without prior approval. *Please keep mailing list traffic on the list where it belongs!*

Reply by email

Martin Frb
to Bo Berglund: Failed to post via Gmane so trying direct emailing instead: I need to figure out why my…
Bo Berglund wrote 12 lines
Failed to post via Gmane so trying direct emailing instead: I need to figure out why my program uses 10% CPU when it is essentially idle, waiting for a client connect via TCP or for the time for a new task start to arrive. It is a command line program running as a service on Linux (Raspberry Pi4). Developed on the RPi4 with Lazarus 2.0.12 and FPC 3.2.0 This is the main loop in the program following creatrion of the handler objects (which are idle): While not (bSTerm or bSInt or bsHup) do begin //Eternal loop to wait for system messages CheckSynchronize(5); //Timeout here instead of using sleep

I think "5" is too small a timeout. So this could keep your system busy. Even if it would be less than 10%, it will prevent your system from ever entering any idle/power saving state.

Ideally you should not need a timeout.
If any code (in a thread) sets any of the variables, it should sent a message to wake the CheckSyncronize.

If of course those vars are set in interrupts, then you can not send a wake up, because any work in interrupts is dangerous.... In that case set the timeout to at least 50. Ideally even higher.

You can have any thread checking the vars, before they do any work (or even while the do work).
Threads can then abort, and send a wake up.
So a longer delay, would not mean any work being done in that time. It would only mean the app shuts down a bit later. IMHO in that a scenario, you could probably up the timeout to 100 or even 200 ms.
Well I don't know how urgent you need your app to exit or reload config, or...
(Assuming that no-one changes the config that should be loaded in that 200ms, and no thread starts work on the old because they all check the flag.... then the delay should not hurt)

Also maybe there is a wait or select call, that would return if an interrupt was received. (IIRC select does that). Then your threads would have to use whatever you select on, in order to communicate with the main thread....

Reply by email