Performance issue on complex WPF application, how to solve that? - wpf

I have my main window at something like 6000 x 6000 px. In that window, I can have a lot of controls (more than 5000) and we can zoom/pan where we want.
I added 10 "television screens" controls in my application, and each of them have a refresh rate of 100ms.
When I start this, everything crash...
10 objects with a refresh rate of 100ms each is too much, WPF cannot draw them at the time. I conclude that WPF is very slow to draw what I have....
Everything is drawn in vector, but I tried to add .CacheMode on them and it doesn't work either..
What can I do?
P.S. My PC is 8 core, 8 GB Ram, 256 Mb video card (nvidia quadro nvs 295) on win7 64bits

WPF uses software rendering in case you exceed maximum supported resolution of you graphics adapter. Moreover, 5k controls! Incredible. WPF is not a silver bullet for everything you imagine. You need to redesign your app or change technology you're using.

Work on reducing the number of controls in your application. 5K is quite a bit, and I think there is probably a way to reduce that number.
For example, use TextBlocks instead of Labels as TextBlocks render as 1 control while Labels render as 3 in 4.0 (I think its more than 3 in older versions)
Also, check and see if you can use UI Virtualization with some of your controls. Something like a ListBox of 100 items can be virtualized to only render 10 of them at a time.

Take a look at ZoomableCanvas - 1 million items. This is the best example out there of what WPF can do when using every optimisation in the book. I suggest you take that example and run it at the maximum resolution on your monitors. If that fails to perform well, then WPF cannot do this.
I was unaware that WPF default to software rendering if the resolution exceeds that of the video card. A good caveat to know about!
Regarding high performance graphical APIs I second Keiren and say use DirectX (SlimDX provides a managed wrapper) instead.

Related

WPF Performance rendering for custom sound wave control

I'm currently looking at writing a sound wave visualisation control for WPF. In fact it can render any sort of line graph data; it doesn't have to be a sound wave. As long as the data is a discrete set of samples it will render it.
I have it working; however the performance is not that desirable. I have done a lot of code optimisation to make the OnRender method work quickly. I've tested it with a profiler and it shows it runs at around 110ms, which should be fine.
However I'm seeing the application stall a lot and the profiler isn't showing why.
During my tests I've noticed it may have something to do with fill rate. By that I mean the number of pixels being drawn. My test data consists of a sin wave, at 41000hz over 20 seconds. This produces 812000 samples. Now my control optimises this data depending on the zoom scale the user is viewing the wave at. The entire wave will be drawn using around 6000 lines draws.
If I zoom a long way into the wave so I only render two full sin waves, I still do around 6000 line draws. The CPU time is around the same, at 110ms but the application is smooth and doesn't stall, which seemed strange at first.
However when looking at it the full wave draw touches almost every pixel. The chart draws a green line, which when zoomed out overwrite the entire background of the graph control. When zoomed all the way in only a small amount the background is overdrawn.
I work as a game programmer so I recognise this issue could be caused by fill rate limits. If the line draw is touching every pixel then it becomes slow to draw, irrespective of the number of line draws. However I would not expect this to be the case as the graph isn’t that large on screen. If I change the size of the window then it does get slower, which again reinforces by guess at fill rate issues. A modern graphics card should be able to handle this so maybe the control is using software rendering. I'm not sure how I can prove that!!
So my OnRender method is pretty optimised as far as the logic goes. In both of the above cases the time it takes to draw, on the CPU, doesn't change much. However in some cases there is a terrible lag of around one second if a lot of pixels are touched.
Does anyone know how I could improve this?
One way I have considered is to render an off screen texture on another thread and once complete, then call InvalidateVisual once the texture has been updated. I could also do the invalidation every so often so the graph rendering updates over time, rather than just suddenly appears.
Anyone have experience of this sort of thing and how do I actually profile the internals of WPF?
Does anyone know a profiler that will show me what is actually causing this, but as I said I think it maybe down to the actually hardware render and a fill rate problem.
Just to note, my graph control inherits from Canvas and the line draw is done using StreamGeometryContext. I also freeze the geometry and all the brushes and pens.
Thanks
I write software that needs to graph large amounts of frequency sprectrum data very fast. WPF's retained graphics system isn't very good for drawing (graphing) large amounts of data that is changing frequently. We use D3D9 to draw our graphs. WPF provides a way to get this into their rendering system through the D3DImage class where it can become an ImageBrush. Thus, it avoids problems relating to airspace restrictions at the cost of a little performance, but will still be much faster than rendering with WPF objects.
There are also two very good graphing libraries that I have seen out there that have different pros/cons.
SciChart is actually a software based rendering charting tool for WPF but has good performance.
Lightning Chart Uses DirectX (Via SlimDX library which is a managed .NET wrapper) and is extremely performance oriented.
Regarding your question about software rendering... The WPF Performance Suite has profiling tools and overlays that can show which portions of your application are being software rendered. You may want to download it from Microsoft and give it a try.
From what I've read, WPF's rendering system is hardly optimal (A Critical Deep Dive into the WPF Rendering System). For what WPF is designed for, it is great, but it has its limits as well.
My recommendation is that if you have experience in game development and DirectX, and you need a method to graph larger amounts of data quickly, to look through interop with D3D via the D3DImage class in WPF.

When using a DirectX-based API with WPF (i.e. SlimDX, SharpDX, etc.) can you do sub-window-sized controls?

In our WPF application, we have a need to display about 64 real-time level meters for an audio application. The tests we've thrown at WPF, even when rendering basic primitives as efficiently as we can still show it to be nowhere near where our application needs to be, often times bogging down the main thread so much to the point that it's non-responsive to input.
As such, we have to go with something more optimized for graphics performance such as DirectX (via SlimDX or SharpDX) or OpenGL/ES (via Atlas which converts it to DirectX calls.)
My question is if it's possible to create multiple, small DirectX-based areas, each representing an individual meter, or for that matter, is that even the right approach? I was under the understanding that you have to run it as at a minimum, the entire window, not a portion thereof.
The issues I see with the latter are airspace issues wherein you can't have WPF content in front of DirectX content in the same window, and we really don't want to have to redo all of our controls in DirectX since for the other non-meter 95% of our UI WPF is great!
I have read that you can render DirectX to a brush, then use that inside WPF, or using the WriteableBitmap class which gives you direct access to the buffers WPF then uses in its Render thread, both of which don't seem to suffer from the Airspace issues, but that seems we'd be right back at the same place with WPF being the bottleneck since it still has to do the rendering.
We are of course going to dedicate a few weeks to sample applications testing all of the above, but I'm wondering if I'm even headed in the right direction, and/or if there are any caveats we can avoid by talking to people with experience doing something like this to avoid common pitfalls, etc. As such, any comments will be appreciated.
I'm hoping we can perhaps even start a wiki somewhere to discuss this topic as it seems to be a popular one, albeit spread all over the place making it hard for new entrants to get the information they seek.
With wpf / d3d interop, You should always try to create the smallest number of interop calls. So you should prefer rendering all 64 level meters in a single render target (also it allows you to batch your primitive rendering and draw everything in the smallest number of gpu calls).
you should try to use the D3DImage API that allows you to share your own D3D texture with the wpf renderer.
If WPF can't really handle these 64 moving bars, you could go with a single D3DImage and use Direct3D9 for rendering all bars at once directly to it. For your specific scenario, you shouldn't have any performance problem.

OpenTK, SharpGL and WPF

I am about to begin a new project. Some decisions are out of my control: Using WPF and OpenGL are some of them.
However, I have narrowed down my OpenGL options to two: Either OpenTK or SharpGL. SharpGL has a WPF control, while OpenTK only has a Windows Forms control, which makes it that I have to embed it in a Windows Forms Host :-/
While I don't mind the airspace restrictions, I do wish to have decent performance, since I am building a real time application. Not a game, but still, real time.
How much of a performance hit would my program take for using OpenTK over a Windows Forms Host, vs using SharpGL with a "pure" WPF control?
When it comes to performance, I can actually only give you a single answer: Do a benchmark yourself! But as you are asking for an elaborate guess:
SharpGl should require an indirection step less, as it leaves out the Windows Forms host control as an "intermediate" blitting target. Take this with a grain of salt though, I have neither looked at the source nor tested it myself.
But practically speaking: The performance should be very similar. At the end of the day the computational heavy operations will probably be the rendering itself, which is done by OpenGL. Blitting the finished result should only take a fraction of that time. So I hope that, however you decide, none of these options would really hurt your performance.
For the sake of the argument: Lets assume the rendering itself (the OpenGL part) takes 16 ms, so we would have a theoretical perfomance of about 60 FPS. Framework A adds an overhead of 1 ms, Framework B an overhead of 4 ms. Even with this quite gross difference in the overhead, Framework a would render at ~ 58 FPS and Framework B at ~ 50 FPS. So in both cases, the application should remain usable.
But what puzzles me is how much you are wondering about this aspect. In the end you are doing work with OpenGL and it shouldn't be too much of a hassle to simply switch the underlying implementation in case things go bad? The interfaces don't seem too different to me.
I would say go with OpenTK, or if it's more comfortable for you to use SharpGL, then go with it in Winforms mode and embed it inside a WPF application.
The reason is that the OpenGL driver knows how to work with a window handle, provided with every winforms control. In a WPF application there is only one window handle, the one of the main window. You may try to use it, but I think it will pose too many problems.
If you don't want things to get rendered directly to screen, and you think of using a PixelBufferObject or a RenderBufferObject, than you will probably be okay with SharpGL in WPF mode (it renders to a RenderBufferObject, than places the resulting buffer in an image, probably using a WritableBitmap or so), or you can do the same thing yourself.

Real-time WPF chart .Net 4

I'm working on a diagnostic tool and receives data every 25 ms. I need this data to be drawn in my chart using a lineSeries. I'm using a a wpf chart with a lineSeries which I bind in xaml to an ObservebleCollection.
The problem is that I need the collection needs to contain atleast 1600 datapoints before starting to remove them at the front.
I understand that 25 ms is a short tiem then it comes to drawing in wpf. Dose anyone have any solution to my problem?
Regards
You should check out SciChart, which can handle data updates at 1ms. It renders like a game-loop, so only draws when new data is appended and the UI thread is free. Some more information at www.scichart.com/wpf-chart-features which shows the features and talks about performance.
Disclosure: It's my own component, so ask any questions if you have them!
I'd suggest you use a custom made drawing routine utilizing WritebleBitmap instead of shapes and draw your lines in a fixed area one segment at a time without any scrolling. The, when you reach 1600 points at the right side of your plot area, start over. Maybe some visual indicator (like vertical line or something) would help perception.
I don't think there any charting libraries targeted at updating 1600 point line every 25ms.
I have a .NET application that charts many measurements on a 33ms interval. I tested a number of charting solutions to accomplish this task, but the only real viable option I found was Arction LightningChart (http://www.arction.com). Lightning Chart will do what you want pretty easily, and I think you can get the basic version for free. The downside will be a dependency on DirectX and the SlimDX library. The trial that you can download from the site will give you pretty good examples of how to use this control in WPF and Windows Forms.
Use Microsoft Chart for WinForms using the WindowsFormsHost control. MS-Chart can handle such data rates well. It internally uses the WritableBitmap method, so it is both fast and stable. Also, don't forget to set the series type to FastLine to avoid slowdown.
I've created a "Tip" article on codeproject which tries to highlight this type of high-data volume usage on MS-Chart. You can change the timer interval to even 1 ms. and see that there is no issue in showing the data.
The article is at http://www.codeproject.com/Tips/1006180/Using-Microsoft-Chart-in-WPF

WPF Architecture and Direct3D graphics acceleration

After reading the wikipedia article on WPF architecture, I am a bit confused with the benefits that WPF will offer me. (wikipedia is not a good research reference, but i found it useful). I have some questions
1) WPF uses d3d surfaces to render. However, the scenegraph is rendered into the d3d surface by the media integrated layer, which runs on the CPU. Is this true ?
2) I just found out by asking a question here that bitmaps dont use native resources. Does this mean that if i use alot of images, the MIL will copy each when rendering, rather than storing the bitmaps on the video card as a texture ?
3) The article mentions that WPF uses the painters algorithm which is back to front. Thats painfully slow. Is there any rational why WPF omits using Z-buffering and rendering front to back ? I am guessing its because the simplest way to handle transparency, but it seems weak.
The reason i ask is that i am thinking it wont be wise for me to put hundreds of buttons on a screen even though my colleagues are saying its directx accelerated. I dont quite believe that whole directx accelerated bit about WPF. I used to work on video games and my memory of writing d3d and opengl code tells me to be cautious.
For questions #1 and #3 you might want to check out this section of the SDK that discusses the Visual class and how it's rendering instructions are exchanged between the higher level framework and the media integration layer (MIL). It also discusses why the painters algorithm is used.
For #2, no that is most definitely not the case. The bitmap data will be moved to the hardware and cached there.
I tested that, I wrote two programs that show 1,000 buttons on screen, one in WinForms and one in WPF, both worked just fine.
I then pushed that up to 10,000 buttons, at that point the WPF app took a few seconds to start but run just fine, the WinForms app didn't start.
Win32 itself (and WinForms) isn't built for applications with hundreds of controls (believe me I wrote such an app), at some point it just stops working, WPF on the other hand, keeps working even if it slows down a bit at some point.
So, if you do need to put a lot of controls on screen WPF is your best bet (unless you want to roll your own UI framework - and you think you can do better than the entire MS perf team).
Also, WPF has many advantages other than graphics acceleration: richer graphics, drawing model that is easier to work with, animations, 3d and my personal favorite - amazing data-binding.
This will let you develop richer UIs faster - and I think that will make a much bigger difference than the painting algorithm used.
BTW, if you need to put hundreds of buttons on the screen this is likely to be a bad user experience and you may want to reconsider your UI design,

Resources