windowsperformancedelphiwindows-server-2019delphi-2006

Windows slowing down with mouse pointer on destop


I've a strange problem. I started approx. 160 processes. Now, if the mouse pointer is on the Desktop, some actions which used to take 100ms, now take 10 seconds although the total load of the system is 13-16%. Even thrid party programs like processhacker slowing down and doesn't refresh their gui. If I move the mouse pointer over some window no matter which one (could be notepad) even the taskbar can help all goes back to normal. Processhacker is refreshing his lists and the responsivness is back to 100ms. Since Microsoft-Support won't help use - since or processes are programmed in Borland-Delphi we have no idea how to find out what's going on here. A colleague tries to reproduce the effect with this little test program:

unit Unit1;

interface

uses
  Forms,
  ExtCtrls,
  Classes,
  Controls,
  StdCtrls;

const
  DEFAULT_INTERVAL = 31;
  MOD_VALUE = 5;
  MOD_INTERVAL = DEFAULT_INTERVAL * MOD_VALUE;
  DEVIATION_BLACK = 2;
  DEVIATION_RED = 10;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    Timer: TTimer;
    lastTime: TDateTime;
    procedure OnTimer(Sender: TObject);
    procedure SetLabel(lbl: TLabel);
  end;

var
  Form1: TForm1;
  GCounterT: Integer;

implementation

uses
  Windows,
  Graphics,
  SysUtils,
  DateUtils;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Self.DoubleBuffered := True;

  Timer := TTimer.Create(nil);
  Timer.Interval := DEFAULT_INTERVAL;
  Timer.OnTimer := OnTimer;

  GCounterT := 0;
  lastTime := Now();
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Timer.Free;
end;

procedure TForm1.OnTimer(Sender: TObject);
begin
  Inc(GCounterT);
  if (GCounterT mod MOD_VALUE) = 0 then begin
    SetLabel(Label1);
    GCounterT := 0;
  end;
end;

procedure TForm1.SetLabel(lbl: TLabel);
var
  newValue: string;
  nowTime: TDateTime;
  msDiff: Integer;
  newColor: TColor;
begin
  if IsIconic(Application.Handle) then Exit;

  nowTime := Now();
  msDiff := MilliSecondsBetween(nowTime, lastTime);
  lastTime := nowTime;

  newValue := Format('TTimer:      %s  dev: %d',[FormatDateTime('ss.zzz', nowTime), msDiff - MOD_INTERVAL]);
  if   (msDiff <= (MOD_INTERVAL + DEVIATION_BLACK))
   and (msDiff >= (MOD_INTERVAL - DEVIATION_BLACK)) then
    newColor := clGreen
  else if (msDiff <= (MOD_INTERVAL + DEVIATION_RED))
   and    (msDiff >= (MOD_INTERVAL - DEVIATION_RED)) then
    newColor := clBlack
  else
    newColor := clRed;
  try
    lbl.Font.Color := newColor;
    lbl.Caption := newValue;
  except
  end;
end;

end.

The effect in not as strong as with the original processes, but it's reproduceable. If one starts 180 of this you can see the same effect only the slowdown is not that severe.

Update Aug 04: I've added a screenshot from a WPA-Analyze-Session. Here one can see the sequence. Starting with mouse on a Window, then Desktop, Window, Desktop and ending with mouse on Window. You can see, that the Thread: CSwitch count is going nearly half if the mouse is on the Desktop. What you also could see is that the system load is between 10-17% the whole time. enter image description here


Solution

  • After we managed to add debug-symbols to some of our processes, we found the issue in the Delphi-VCL/Forms.pas. In a new trace, with debug-symbols, we saw that the Application.DoMouseIdle method spends a lot of time finding VCLWindows, get Parents of these and so on. The source of the slowdown is the "FindDragTarget" method. Our processes need no drag'n'drop functionality and they need no hint showing somewhere. So we cut this function call out of the code, which was not easy. Now everything is running fast undependend from the mouse position.