0

I have been working for 2.5 years on a personal flight sim project on my leisure time, written in C++ and using Opengl on a windows 7 PC.

I recently had to move to windows 10. Hardware is exactly the same. I reinstalled Code::blocks.

It turns out that on first launch of my project after the system start, performance is OK, similar to what I used to see with windows 7. But, the second, third, and all next launches give me lower performance, with significant less fluidity in frame rate compared to the first run, detectable by eye. This never happened with windows 7.

Any time I start my system, first run is fast, next ones are slower.

I had a look at the task manager while doing some runs. The first run is handled by one of the 4 cores of my CPU (iCore5-6500) at approximately 85%. For the next runs, the load is spread accross the 4 cores. During those slower runs on 4 cores, I tried to modify the affinity and direct my program to only one core without significant improvement in performance. The selected core was working at full load, though.

My C++ code doesn't explicitly use any thread function at this stage. From my modest programmer's point of view, there is only one main thread run in the main(). On the task manager, I can see that some 10 to 14 threads are alive when my program runs. I guess (wrongly?) that they are implicitly created by the use of joysticks, track ir or other communication task with GPU...

Could it come from memory not being correctly freed when my program stops? I thought windows would free it properly, even if I forgot some 'delete' after using 'new'.

Has anyone encountered a similar situation? Any explanation coming to your minds?

Any suggestion to better understand these facts? Obviously, my ultimate goal is to have a consistent performance level whatever the number of launches.

trying to upload screenshots of second run as viewed by task manager:

2nd run

trying to upload screenshots of first run as viewed by task manager:

1st run

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
YannOO
  • 11
  • 2
  • 4
    Does your code use `timeBeginPeriod`, `timeEndPeriod`, or `Sleep`? Have you tried profiling the code to see where the performance difference occurs? – Retired Ninja Mar 23 '22 at 20:18
  • Does your program's process actually terminate after the first launch, before you launch it a second time? If that is the case, then unfreed memory should not be an issue, as it should be automatically freed by the operating system's kernel. – Andreas Wenzel Mar 23 '22 at 20:20
  • You may want to check your CPU's and GPU's temperature. If either of them is being throttled due to overheating, then that would explain why your PC is faster on the first launch and gets slower over time. – Andreas Wenzel Mar 23 '22 at 20:22
  • Usually, it's exactly the opposite: first run is slower than the next ones, thanks the cache. Last time I encountered something like you did, it was zombie processes who were still running and sucking CPU time like hell... It wasn't only MY application that was slower, ALL applications were slower. Check this. CPU/GPU average load shouldn't be different before and after the first run (if needed, wait a full minute before/after to get better values). – Wisblade Mar 23 '22 at 22:24
  • @RetiredNinja : No, my code doesn't use those instructions. I am not familiar with profiling techniques yet. Any tools or tuto I could benefit from ? – YannOO Mar 24 '22 at 07:06
  • @AndreasWenzel : Yes, my program correctly terminates after the first launch. The GPU temp stabilizes at around 30°C. I don't know how to check CPU temp. – YannOO Mar 24 '22 at 07:23
  • @Wisblade : You're right. This is what I used to get in windows 7 : the first run was slower, especially when loading the data at the beginning of the run. Once data were loaded, I don't remember any significant difference between runs. – YannOO Mar 24 '22 at 07:25
  • @all : I edited my initial question and added some screenshots. – YannOO Mar 24 '22 at 07:35
  • @YannOO: A GPU temperature of 30 degrees celsius is very good, so that is not the problem, assuming that the temperature stays in that range. You should of course measure the temperature **immediately after** you experience the problem, not beforehand, because it is normal for the temperature to be low before you put a strain on the GPU/CPU. – Andreas Wenzel Mar 24 '22 at 12:23
  • @YannOO: The easiest way to check the CPU temperature would probably be to go into BIOS/CMOS settings while your computer is starting up, before Windows is loaded. Most modern BIOSes also provide access to hardware data - such as CPU temperature - in those menus. On my computer, you must hold the button down while starting up, to get into that menu. You can probably also install software that is able to read that data from the hardware, if you find that more convenient. However, I have no experience with using such software, so I cannot provide a recommendation. – Andreas Wenzel Mar 24 '22 at 12:27
  • I strongly advise you to use a profiler. Such problem is certainly non-trivial and using the (very) basic Windows tools is like trying to detect a whale from a beach only with your eyes. A great famous free tool to do that is Intel VTune. Without profiling information reported nor any code, I doubt anyone can find the answer (except by chance combined with some guessing). – Jérôme Richard Mar 24 '22 at 19:28
  • @JérômeRichard : I'm currently doing my first attemps with the profiler included in code::blocks + MinGW 64 tools. One weird thing is that the gmon.out file is not generated by my first run from code::blocks, while it is generated by next runs. So I can't compare first run profile data with next runs profile data. However, might this be a clue that the problem is coming from code::blocks launching my program differently between a first run an the next ones ? – YannOO Mar 25 '22 at 11:18
  • Hi ! I finally managed to solve my problem. With the profiler I identified a function which was time consuming. In this function,called on every frame, I was using a lot of glGetUniformLocation to set uniforms in shaders next. I realized that this was asking the gpu the location of uniforms every frame while a single time was necessary after shaders compilation. Probably because of some sort of cpu/gpu synchronization mechanisms this was slow. I still don't understand why it was on second, third, etc runs and not on the first one. I don't understand why it never happened with Win7. – YannOO Apr 02 '22 at 18:45

1 Answers1

0

Well I got a problems when switching to win10 for clients at my work too here few I encountered all because Windows10 has changed up scheduling of processes creating a lot of issues like:

  1. older windowses blockless thread synchronizations techniques not working anymore

    well placed Sleep() helps sometimes. Btw. similar problems was encountered when switching from w2k to wxp.

  2. huge slowdowns and frequent freezes for few seconds on older single threaded apps

    usually setting affinity to single core solves this. You can do this also in task manager just to check and if helps then you can do this in code too. Here an example on how to do it with winapi:

  3. messed up drivers timings causing zombies processes even total freeze and or BSOD

    I deal with USB in my work and its a nightmare sometimes on win10. On top of all this Win10 tends to enforce wrong drivers on devices (like gfx cards, custom USB systems etc ...)

  4. auto freeze close app if it does not respond the wndproc in time

    In Windows10 the timeout is much much smaller than in older versions. If the case You can try running in compatibility mode (set in icon properties on desktop) for older windows (however does not work for #1,#2), or change the apps code to speed up response. For example in VCL you can call Process Messages from inside of blocking code to remedy this... Or you can use threads for the heavy lifting ... just be careful with rendering and using winapi as accessing some winapi (any window/visual related stuff) functions from outside main thread causes havoc ...

On top of all this old IDEs (especially for MCUs) don't work properly anymore and new ones are usually much worse (or unusable because of lack of functionality that was present in older versions) to work with so I stayed faith full to Windows7 for developer purposes.

If none of above helps then try to log the times some of your task did need ... it might show you which part of code is the problem. I usually do this using timing graph like this:

timing graph

both x,y axises are time and each task has its own color and row in graph. the graph is scrolling in time (to the left side in my case) and has changeable time scale. The numbers are showing actual and max (or sliding avg) value ...

This way I can see if some task is not taking too much time or even overlaps its next execution, peaks are also nicely visible and all runs during runtime without any debug tools which might change the behavior of execution.

Spektre
  • 49,595
  • 11
  • 110
  • 380