title: Same code runs slower as a Windows service than a GUI application
body: <p>I have some Delphi 2007 code which runs in two different applications, one is a GUI application and the other is a Windows service. The weird part is that while the GUI application technically seems to have more "to do", drawing the GUI, calculating some stats and so on, the Windows service is consistently using more of the CPU when it runs. Where the GUI application uses around 3-4% CPU power, the service use in the region of 6-8%. </p>
  
  <p>When running them together CPU loads of both applications approximately double.</p>
  
  <p>The basic code is the same in both applications, except for the addition of the GUI code in the Windows Forms application.</p>
  
  <p>Is there any reason for this behavior? Do Windows service applications have some kind of inherent overhead or do I need to look through the code to find the source of this, in my book, unexpected behavior?</p>
  
  <h1>EDIT:</h1>
  
  <p>Having had time to look more closely at the code, I think the suggestion below that the GUI application spends some time waiting for repaints, causing the CPU load to drop is likely incorrect. The applications are both threaded, meaning the GUI repaints should not influence the CPU load. </p>
  
  <p>Just to be sure I first tried to remove all GUI components from the application, leaving only a blank form. That did not increase the CPU load of the program. I then went through and stripped out all calls to Synchronize in the working threads which were used to update the UI. This had the same result: The CPU load did not change.</p>
  
  <p>The code in the service looks like this:</p>
  
  <pre><code>procedure TLsOpcServer.ServiceExecute(Sender: TService);
  begin
    // Initialize OPC server as NT Service
    dmEngine.AddToLog( sevInfo, 'Service', 'Name', Sender.Name );
    AddLocalServiceKeysToRegistry( Sender.Name );
  
    dmEngine.AddToLog( sevInfo, 'Service', 'Execute', 'Started' );
    dmEngine.Start( True );
    //
    while not Terminated do
    begin
      ServiceThread.ProcessRequests( True );
    end;
  
    dmEngine.Stop;
    dmEngine.AddToLog( sevInfo, 'Service', 'Execute', 'Stopped' );
  end;
  </code></pre>
  
  <p>dmEngine.Start will start and register the OPC server and initialize a socket. It then starts a thread which does... something to incoming OPC signals. The same exact call is made on in FormCreate on the main form of the GUI application.</p>
  
  <p>I'm going to look into how the GUI application starts next, I didn't write this code so trying to puzzle out how it works is a bit of an adventure :)</p>
  
  <h1>EDIT2</h1>
  
  <p>This is a little bit interesting. I ran both applications for exactly 1 minute each, running AQTime to benchmark them. This is the most interesting part of the results:</p>
  
  <h2>In the service:</h2>
  
  <p><em>Procedure name:</em> TSignalList::HandleChild</p>
  
  <p><em>Execution time:</em> 20.105963821084</p>
  
  <p><em>Hitcount:</em> 5961231 </p>
  
  <h2>In the GUI Application:</h2>
  
  <p><em>Procedure name:</em> TSignalList::HandleChild</p>
  
  <p><em>Execution time:</em> 7.62424101324976</p>
  
  <p><em>Hit count:</em> 6383010</p>
  
  <h1>EDIT 3:</h1>
  
  <p>I'm finally back in a position where I can keep looking at this problem. I have found two procedures which both have about the same hitcount during a five minute run, yet in the service the execution time is much higher. For HandleValue the hitcount is 4 300 258 and the execution time is 21.77s in the service and in the GUI application the hitcount is 4 254 018 with an execution time of 9.75s.</p>
  
  <p>The code looks like this: </p>
  
  <pre><code>function TSignalList.HandleValue(const Signal: string; var Tag: TTag; const CreateIfNotExist: Boolean):        HandleStatus;
  var
    Index: integer;
  begin
    result := statusNoSignal;
    Tag := nil;
  
    if not Assigned( Values ) then
    begin
      Values := TValueStrings.Create;
      Values.CaseSensitive  := defDefaultCase;
      Values.Sorted         := True;
      Values.Duplicates     := dupIgnore;
      Index := -1;  // Garantied no items in list
    end else
    begin
      Index := Values.IndexOf( Signal );
    end;
  
    if Index = -1 then
    begin
      if CreateIfNotExist then
      begin
        // Value signal does not exist create it
        Tag := TTag.Create;
        if Values.AddObject( Signal, Tag ) &gt; -1 then
        begin
          result := statusAdded;
        end;
      end;
    end else
    begin
      Tag := TTag( Values.Objects[ Index ] );
      result := statusExist;
    end;
  end;
  </code></pre>
  
  <p>Both applications enter the "CreateIfNotExist" case exactly the same number of times. TValueStrings is a direct descendant of TStringList without any overloads.</p>