1

Background:

Our product has one instance of dedicated application (Win32 Delphi) for each device connected to our system. Recently we have a huge project where over 100 devices were connected, so our control application started 140-160 Win32 applications. Every application has its timer, and we have seen that ALL timers tick slower, when mouse cursor points to desktop.

Problem:

After experimenting i found out, that it is not a timer problem, but the speed of message pump processing.

Tests:

I have created test application, that has 3 different timers: simple Delphi TTimer (actually SetTimer/KillTimer inside), QueueTimer using messages for calling callback routines, and QueueTimer calling direct callback routines. Test app has also 3 labels to show time when timer tick happened. All timers tick every 20 mS, and every 10 ticks (=200 mS) test app refreshes label for particular timer.

Problems start to happen when I start more than 110 applications (minimized). After restoring one app from minimized state, i can see, that if mouse cursor points to ANY window (test app window, task manager, Notepad, even windows taskbar) - then all timers tick as expected (surely TTimer isn't that precise as QueueTimer, but still in acceptable range). But as soon as mouse cursor points to windows desktop (including any shortcut in desktop) - then i see, than ticks from timers, that use messages, come much slower as before. Only QueueTimer, that uses direct callbacks, continues to tick with same speed.

Question:

Is there any way to disable such "feature" of Windows?

Tested and reproduced on:

  • W7 + Intel Xeon (4 cores) + NVidia (256MB RAM) + 16GB RAM,
  • W10 + Intel Xeon (4 cores) + NVidia (256MB RAM) + 16GB RAM,
  • W2016 Server + Intel 16 cores + 64GB RAM + AMD Radeon (1 GB RAM).

All windows visual effects (like mouse pointer shadow etc.) are off, it happens as well with desktop solid color background.

I have really no ideas how to change this windows behaviour. I tried to change windows desktop heap size without any effect.

If some additional information is needed (code samples, compiled apps) - pls let me know.

Vasilich
  • 83
  • 7
  • Could you give numbers about the slow down ? – fpiette May 19 '20 at 13:41
  • Well, as a side effect - all apps (including .NET), that normally take 2 seconds to start, in that case take more than 30 seconds, so the slowness rate is (rough) 10 to 20. – Vasilich May 19 '20 at 13:46
  • I understand your apps starts slowly when the mouse cursor fly over desktop, but how can you relate the slowdown with the message pump? Maybe it is a side effect of "priority boost" (https://learn.microsoft.com/en-us/windows/win32/procthread/priority-boosts)? – fpiette May 19 '20 at 13:51
  • Not only my apps - all apps starts to react/start slowly. VS Code, Windows explorer, LINQPad, literally everything. And priority boost should work for processes in foreground. In that case i don't change focus to desktop, i just move mouse away from any window. I see correlation in slowness to message pump is that if i use same code - once with messages, and once - without it, then i clearly see that the component without messages is not affected, whereas other usage with messages slows down. – Vasilich May 19 '20 at 14:13
  • Before starting to troubleshoot further set the power plan to High Performance. – Brian May 19 '20 at 15:42
  • It was already set to HiPerformance, with min and max values for CPU speed both to 100% – Vasilich May 19 '20 at 16:04
  • WM_TIMER is a low priority message by design. It is not suitable for anything even remotely requiring regular or real-time control. From [the docs](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-timer) : `The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue.` If you're interacting with hardware, use a dedicated thread. Don't rely on timer messages because... you can't. – J... May 19 '20 at 16:51
  • I am aware of it. That is why in my test app i use Timer (which uses internally WM_TIMER) just to compare it with other ways, and QueueTimer with calling callbacks using user message (e.g. WM_USER+41). Moreover, if i use Synchronize for moving callback to main thread, it also internally uses its own message (not WM_TIMER), and this one also suffers from performance degradation. QueueTimer implementation without messages works perfect in all cases. – Vasilich May 19 '20 at 17:18
  • 1
    @Vasilich Yeah, don't use Synchronize either - then you're at the mercy of whenever `CheckSynchronize` gets called. Whatever is controlling your hardware doesn't need to care about the UI thread at all - so don't strangle it with a main thread burden at all. Just talk to the hardware from your thread directly. Now you don't have to worry about what the UI thread is doing... because you shouldn't need to. – J... May 19 '20 at 17:22
  • Although this may tempt you down a dark path of hacking this poor architecture into working by messing with process priorities, you may want to read about [process scheduling](https://learn.microsoft.com/en-us/windows/win32/procthread/priority-boosts) in windows. – J... May 19 '20 at 19:47
  • Yes, @fpiette already thought about it in its earlier comment. In my test app there is no hardware controlling at all. I have also tried to check somehow whether any processs gets priority boost while mouse cursor reaches desktop - no, no prio boost (at least ProcessHacker doesn't show it); I have tried to set root Explorer.exe and dwm.exe to idle priority - no changes at all, still slowdowns. Is there any way to disable priority boosting completely, to check whether it can be a culprit? – Vasilich May 20 '20 at 07:56
  • **come much slower as before** . How many milliseconds slower than before? I can't reproduce your problem, can you provide a minimal example? – Strive Sun May 20 '20 at 10:17
  • 1
    @Vasilich I wouldn't bother, to be honest. Why not just fix the bad design decision instead of stubbornly trying to find a way to force it to work? – J... May 20 '20 at 10:20
  • @J... What do you mean under bad design? Again, the test app doesn't have any connection to hardware - just timers that print its values. – Vasilich May 20 '20 at 12:49
  • @StriveSun-MSFT as i said before - about (rough estimation) 10-20 times slower. I put the test project (Delphi 2006) and compiled file here (in case someone can compile it or start compiled app in Release folder) https://cloud.bfe.tv/index.php/s/jcwltVx6SBSpQ0L/download – Vasilich May 20 '20 at 13:03
  • 1
    @Vasilich By 'bad design' I guess I mean this idea of spinning off 150 separate processes and insisting on coupling UI dependencies on your hardware interaction code. The UI thread of a windows application has one purpose - to drive the user interface. If the user has minimized that interface it doesn't really matter if handlers are a bit late because nobody can even see the form - Windows knows and leverages this (and expects that you do too). Don't put things with non-UI dependencies and non-UI time constraints in UI handlers - it's as simple as that. – J... May 20 '20 at 14:45
  • @J... agree that it was not the best idea to create/design one process per device type. But several years ago noone has expected that there will be so many device manufacturers who will reinvent the wheel and create its own protocol for their device types. But the main problem is the whole PC (all applications, not only ours) becomes so slow, that customer has to wait 20 seconds to open simple windows explorer window! – Vasilich May 20 '20 at 15:40
  • 1
    @Vasilich Indeed, it's called [technical debt](https://en.wikipedia.org/wiki/Technical_debt), and you have to pay for it one way or another. – J... May 20 '20 at 15:47
  • @Vasilich ...so a workaround would be to just maximize a window, so the desktop isn't there anymore? As a long shot: any difference between wallpaper and solid color desktop? Disabling the desktop per policies? Disabling mouse pointer shadow? – AmigoJack May 22 '20 at 00:31
  • @AmigoJack thanks, added info about solid color and visual effects to post. Right now this workaround (maximized window) is in use. But this is really a workaround, and i hope to find a real solution (some desktop heap / process priority setting / whatever else) to this. Not sure that disabling desktop is the solution that satisfies our customer (i haven't tried this yet, so no idea whether that helps). – Vasilich May 23 '20 at 23:52
  • @Vasilich Is this a problem with Delphi only? Have you tried other libs? Such as MFC, .net? – Strive Sun May 25 '20 at 06:49

0 Answers0