2

I have single-thread windows form application written with VB.NET and targeting Framework 1.1. The software communicates with external boards through a serial interface, and it mainly consist of a state machine that run some tests, driven in a loop done with a Timer and an Interval of 50ms.

The feedback on the user interface is done through some custom events raised during the tests.

The problem that is driving me crazy is that the performance slightly decrease over time, and in particular after 1200/1300 test operations. The memory occupied does not increase over time, it is only the CPU that seems interested by this problem.

The strange thing is that, targeting framework 2.0 and using the same identical code, I do not have this problem.

I know that is difficult without looking at the code, but do you have suggestions how can I approach the problem?

EDIT: I am really lost, after a couple of intensive work the application starts slowing down. The selected row is related to its process, if it could help.

EDIT2: Using the Windows Task Manager I detected that the Handles counter is increased by 1 at the end of each operation. I don't know if it is the cause but the application starts to slow down when the handles counter reaches about 1500 handles. I checked that all necessary RemoveHandler are called after each operation. Any idea?

EDIT3: I found that the handles problem is generated by the C++ library we are using to communicated with the serial device. It then happens both in .NET 1.1 and .NET 2.0. The difference, and that's strange, is that if the target .NET 1.1 the application slow down/freeze instead for .NET 2.0 I reached more than 30000 handles without loosing performances. Now I don't know if the problem is really caused by this lost handles, I will try to ask to the developers of C++ library to correct the problem and see if it solves the problem I am having on .NET 1.1.

full image here

alt text

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Drake
  • 8,225
  • 15
  • 71
  • 104
  • 1
    @Chris. If it works with 2.0 why do you need to use 1.1? Have your tried the Red-gate performance profiler (it's excellent). – Jamie Clayton May 20 '10 at 12:48
  • The tool has been written in 1.1 and 1.1 was the required framework. Maybe there are some possibilities to move to framework 2.0, but not sure. I will check the red gate profiler and hope it helps – Drake May 20 '10 at 14:02
  • What does the peak memory usage column tell you? Also, it appears that you are reading 250MB of information, how are you doing that? –  May 20 '10 at 14:58
  • @roygbiv The memory peak tells me 204MB. The big amount of reading is due to the data exchange between PC and external device using serial port – Drake May 20 '10 at 15:28
  • Does the handle leak happen when .NET 2.0 is targeted? – Igby Largeman May 24 '10 at 19:05
  • @Charles Yes, I discovered that it happens with .NET 2.0 too. The difference is that with .NET 1.1 the slow down start when it reach 1300-1500 handles. With .NET 2.0 I arrived at 5000 handles without seeing any performance decrease. – Drake May 25 '10 at 09:50
  • 1
    Any native code which could leak Win32 handles? (Not that there couldn't be a bug / race condition in the .net library) Does the # of handles increase each time the timer loop executes? – MZB May 26 '10 at 21:00
  • @MZB I identified that the handles is lost by the C++ library we are using to communicated with the serail device. It then happens both in .NET 1.1 and .NET 2.0. The difference is that if the target .NET 1.1 the application slow down/freeze instead for .NET 2.0 I reach more than 30000 handles without loosing performances – Drake May 28 '10 at 09:33

4 Answers4

2

Full disclosure: I am on the Visual Studio Profiler team.

Edit: the following is not useful since the VS Profiler does not work with .NET 1.1. Have you tried running your code under a profiler? Visual Studio 2005/2008 (Developmen Edition/Team Suite) and Visual Studio 2010 Premium/Ultimate have a built-in profiler. There are also 3rd party .NET profilers available.

Running your code under the profiler will show you where your CPU is doing a lot of work. If you profile only around the time when performance is degraded, the results should help you see why.

Alternatively, you can simulate cheap profiling: debug your application and break into it periodically to see what's executing on the call stack.


Also, does your machine have .NET Framework 1.1 SP1 installed? Are you able to reproduce this issue on other machines?

Chris Schmich
  • 29,128
  • 5
  • 77
  • 94
  • thank you for support. The issue can be reproduced in different machines, and in all of them SP1 is installed. I did the cheap profiling that you suggested and also print out the stack level of routines but it seems that stack level is low and not growing, less than 50 always. Do you think that it is possible attaching the VS Premium Profiler to .NET 1.1 while it running? – Drake May 20 '10 at 09:07
  • Sorry, I actually forgot, the VS Profiler does not work with .NET 1.1., so no, you can't use that. For the "cheap profiling method", don't worry about the depth of the stack, just break periodically (10 times or so), and keep track of what's executing. If you consistently see the same method(s) executing on top of the stack, then that should help narrow down where the problem is. – Chris Schmich May 20 '10 at 09:10
2

OK, since you can't use the Performance Profiler, I can think of two things to try.

  1. It's the dumb/obvious question. Are you absoutely sure you're Disposing everything that implements IDispose?
    Even if you are sure go back and check again, keep an eye out for temporary objects that won't be disposed e.g.

    string s = objA.GetAThing().ToString()
    

where GetAThing() returns an object that implements IDispose.

  1. Have you tried forcing a Garbage Collection?
    Read Rico Mariani's Performance Tidbits, sometimes it's not only OK to call GC.Collect(), sometimes it's necessary.
    We have a large rich .Net winforms application that on which we need to force a collection every ten minutes or so. If we don't the the application starts to grind after a couple of hours.

Hope this helps :)

UPDATE
Thats a shame. Do you have the C++ source? Or are you stuck with this problem?

If stuck, you can have the application periodically launch a new instance while terminating the current instance.

You can use a locked file or Mutex to ensure the new instance doesn't start processing until the first terminates.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Binary Worrier
  • 50,774
  • 20
  • 136
  • 184
  • Thank you for answering, but I found that the handles problem is generated by the C++ library we are using to communicated with the serial device. It then happens both in .NET 1.1 and .NET 2.0. The difference, and that's strange, is that if the target .NET 1.1 the application slow down/freeze instead for .NET 2.0 I reach more than 30000 handles without loosing performances. – Drake May 28 '10 at 09:35
1

First, I would use the Performance profiler included in windows pretty much as Tess suggests here.

Then I would use windbg much as she suggests here.

I only suggest windbg second because if you have not used it you are in for a little WTF session until you get it (it is entirely worth getting though). Maybe by playing around with counters you can find the issue.

Flory
  • 2,849
  • 20
  • 31
1

Hmmm

With such limited information it could be a million things.

Using a bit of 'Zen' programming I'd say, get rid of the timer and start using Threads.

Use the usual patterns of having a cancel flag, and have the tests run in an a while loop (if that's how its needed).

Darknight
  • 2,460
  • 2
  • 22
  • 26