Benchmarking affected by VCL

2020-02-14 12:27发布

问题:

Today I ported my old memory benchmark

from Borland C++ builder 5.0 to BDS2006 Turbo C++ and found out weird thing.

  • exe from BCB5 runs OK and stable
  • exe from BDS2006 measure OK only before main Form is started (inside its constructor) and if the benchmark is started again after main form is Activated or even after any VCL component change (for example Caption of main form) then the speed of benchmark thread is strongly affected.

After some research I found out that:

  • Does not mater if test is inside thread or not.
  • The process/thread priority,affinity does not affect this either.
  • Hide of any window (Visibility,Enabled) does not affect this.
  • call the test form OnIdleEvent does not affect this
  • does not mater if time is measured by RDTSC or PerformanceCounter

My conclusion is that VCL library runs some code/thread on the background so my questions are:

  1. Is there a way to temporarily pause VCL code/stuff ?

    ideal something like Application->Pause(); and Application->Resume(); or just Forms.

  2. what else could cause this behavior and how to avoid it ?

PS.

Test application has no VCL components other than main form. Benchmark is just a few memory transfers by rep stosd with different block sizes (no funny stuff). Source is in this related Q/A. I know BDS2006 is out-dated but I am not looking for upgrade right now so please skip any comments about that they are not help-full at all.

Tested on Windows7 pro x64, 32bit Application

回答1:

I found out that wndproc in BDS2006::VCL invalidates CACHEs.

  1. I have tried to override wndproc by winapi

    for Application->Handle is this easy but it does not stop the processing of messages for Form. When I tried Form1->Handle as window then error 1400 occurs (not valid window handle)

  2. I have tried to override wndproc by VCL

    for Application by TApplication events and for Form by override of virtual wndproc member. Message processing stops but their calling sequences remains and the problem is not solved either.

So my conclusion after eliminating every possibility I can think off is that I need to flush CACHE more intensively somehow after setting process/thread for benchmarking.

In DOS I would done it by single instruction but on windows it is more tricky. Well The previous version of memory benchmark used just memory filling which is obviously not enough for BDS2006 exe. I think that instruction CACHE is involved in this problem not data cache so I change it a bit and it finally worked thing out.

Flushing the CPU CACHE:

for (DWORD i=0;i<(128<<20);i+=7)
    {
    dat[i]+=i;
    dat[i]*=i;
    dat[i]&=i;
    }

Where dat is 128MB allocated memory chunk (or bigger) and must be done after all process/thread priority and affinity changes or all winapi calls prior to benchmarking.