Welcome to MSDN Blogs Sign in | Join | Help

WPF Performance on Tablet & Touch-enabled machines

Some customers reported performance issues and general sluggishness on Tablet & Touch-enabled machines with their WPF applications. This is especially noticeable during scrolling if the application comprise of many visual elements.

The root cause is that Accessibility clients need to collect UIAutomation information in order interact with applications. This in turn causes WPF to fire UIAutomation events at the end of each layout. 
The current WPF implementation (.NET 3.5 SP1 or earlier) for this scenario is not as optimal since WPF walks every element in the application tree and checks if it need to fire automation event.

Depending on the machine speed and how many elements are in the application visual tree, this can be CPU consuming and cause sluggishness in your app when it needs to do layout.

The issue is mostly noticeable on Tablet and other touch-enabled machines and not on other machines, because TabTip.exe (the “Tablet PC Input Panel”) is an Accessibility client which collects UIAutomation from your WPF app and it is always running by default on all Tablet /touch-enabled machines.

This scenario will be much improved in .Net 4 and we are still looking on how to help .Net 3.5 SP1 customers, so stay tuned.

What can you do in your .Net 3.5 SP1 app in the meantime ?

1. To verify your perf issue is related to this, you can install latest NET 4 RC build and verify the issue is gone (see below). 
    If the perf issue gone and you are still confident it is not related to other issues:

2. Consider disabling Accessibility and UIAutomation for your app.
   
One good example on how to that is to look at the implementation in the WPF Fishbowl Facebook application.
   
You can download sources from here: http://fishbowl.codeplex.com/ . 
   
The app basically disables accessibility by adding these lines of code:

        private class _FakeWindowsPeer : WindowAutomationPeer

        {

            public _FakeWindowsPeer(Window window)

                : base(window)

            { }

            protected override List<AutomationPeer> GetChildrenCore()

            { return null; }

        }

        protected override AutomationPeer OnCreateAutomationPeer()

        { return new _FakeWindowsPeer(this);  }

 

Important Note: This workaround will also disable accessibility for your app so this workaround is not encouraged. Your app will not be available to any Accessibility clients , such as Screen Reader or automation tests, so only do so if you must and cannot for example simplify your app and/or reduce # of elements.

You may also want to consider adding this as an option (e.g. add “Enable Accessibility”  checkbox in your app option dialog) so Accessibility could be available to users that do need it but provide the perf gains to others who don’t.

Note: in most cases you can simply add an <app.config> file for your .Net 3.5 SP1 app for it to run on .Net 4.
For example: to force app to run in NET 4 add <app.config> file and say :

<?xml version="1.0"?>
<
configuration
>
    <
startup
>
              <
supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"
/>
    </
startup
>
</
configuration>

Or for NET4 Client Profile say:
  
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0, Profile=Client"/>

 

Posted by jgoldb | 0 Comments

What’s new in .NET Framework 4 Client Profile Beta 2

Introduction

Hopefully folks have seen Soma’s blog announcing the availability of Beta 2 of Visual Studio 2010 and .NET Framework 4.
In .NET Framework 4 we have introduced a streamlined subset and more compact version of the .NET Framework called the Microsoft .NET Framework 4 Client Profile (aka NET4 Client Profile).
The Microsoft .NET Framework 4 which is the Full Framework (aka NET4 Full) still exists and it is a superset of the Client Profile.

The Client Profile is smaller in size and its goal is to improve the deployment size, time, reliability and overall deployment experience for client applications.

The Client Profile contains the functionality that most common desktop client applications (including Windows Forms and WPF applications) would need, so we expect that many client application developers will target it. This will improve the overall application deployment experience when the application requires .NET Framework 4 to be installed.

One of the most important improvement over NET 3.5 SP1 Client Profile, is NET4 Client Profile is now supporting all platforms and OS's that are supported by the Full Framework including Vista, XP, Win2k3, Win2k8, Windows7, x86/x64 (excluding IA64).

Few desktop applications may still need to target the NET4 Full if they must use features that are not included in the NET4 Client Profile.

My previous blog discussed Beta1, in this blog I will focus on Beta 2.

What are the reasons for a Client Profile?

Keeping the Client Profile small provides:

  • Improve the deployment time of the Framework and the overall deployment time of applications that chain the Framework.
  • Reduce the Framework deployment failures
  • Reduce the redist space that is needed on ISV’s media and allow more space to ISVs applications
  • By keeping ASP.Net and other components (that are mostly needed for servers) out of the Client Profile, the attack surface and the number of future servicing events which may be caused by ASP.Net are reduced.

How big is the Client Profile?

Below are the redistributable download size improvements since NET 3.5 SP1.
This shows that on x86, with NET4 Client Profile you can save up to 86% of the Framework deployment size compare to 3.5 SP1 Full.

Note that if you are downloading from the Web, the actual download size could be smaller since some components may already be on your machines (for example, Windows Imaging Components, Software Rasterizer (rgb9rast) , etc )

 

3.5 SP1

4.0 Beta1

4.0 Beta2

32 bit Client Profile

Online: ~28 MB**

Offline: 255 MB

34.2 MB

30.9 MB

32 + 64 bit Client Profile

N/A

71.3 MB

47.1 MB

32 bit Full

N/A

76.5 MB

37.7 MB

32 + 64 bit Full

N/A

157 MB

54.5 MB

32 + ia64 bit Full

N/A

161.6 MB

56.4 MB

32 + 64 + ia64 bit Full

231 MB

N/A

N/A

** NET 3.5 SP1 Client Profile web download install ~28mb on XP machines that have no framework, it otherwise installs the  NET 3.5 SP1 Full. See more here.

When to use NET4 Client Profile and when to use NET4 Full Framework?

Client Profile:
We recommend that the NET4 Client Profile be utilized as the primary framework for most client desktop applications (including Windows Forms and WPF apps).
Since we are considering to make the NET4 Client Profile available broadly to desktops via Windows Update, most client desktops may have NET4 Client Profile soon after NET4 releases making it ubiquitous*.
Until that time, NET4 apps can chain-install the NET4 Client Profile which is smaller and faster to install.

*Note: This plan is not final.

Full framework:
The Full framework is a superset of the Client Profile. It should mainly be used for:

    • Server apps (e.g. ASP.Net apps)
    • For developer scenarios (for example, this includes msbuild)
    • For all other legacy client scenarios (for example, this includes System.Data.OracleClient.dll which is being deprecated in NET4) that are not included in the Client Profile.

What is new in NET4 Client Profile Beta2 vs. Beta 1?

In Beta2 we made some significant changes to the NET4 Client Profile. The main changes include:

  • Client Profile now included additional functionality such as Speech and WF 4.0. (see list below)
  • To improve NETFX4 install time on 64-bit OS, we postpone NGEN (native image generation) of most 64-bit assemblies (except mscorlib.dll and system.dll) to when the machine is idle. (Typically this corresponds to ~5min of user inactivity).
    The reasons we made this change:
    1. Many new machines now have a 64-bit OS and this number is trending up very quickly. All these machines will benefit from faster NET4 deployment time.
    2. Most client apps on 64-bit OS will still be 32-bit apps running on WOW64, which will not be impacted by this change.
    3. Developers / IT Admins can always force NGEN of all .NET Framework assemblies by calling: "ngen executeQueuedItems 3", or separately NGEN each assembly they need.
    4. By the time we see a significant number of 64-bit apps, NET4 likely to already be ubiquitous and already NGEN’ed.
    5. Visual Studio 2010 has changed the compile default from “AnyCPU” to “x86”. Most developers will not change this, since very few NetFX4 apps have any reason to do so (more in this blog here).
  • Even though we have added a number of components to the Client Profile, with better compression we managed to still keep the Client Profile redist size low (e.g.: Beta 2 x86 is 30.9MB).
  • We removed the XPS Viewer and MSXML 6.0 from the Client Profile redist.
  • Visual Studio 2010 now automatically adds <app.config> (Application Configuration File) to NET4 Full Framework projects an entry to indicate to the CLR that the app requires the Full Framework.
  • By default, if <app.config> is missing from a NET4 app’s directory, CLR assumes that the application is targeting the Client Profile. This prevents apps that require the Full Framework from loading when run on NET4 Client Profile.
  • Note that NET4 Beta1 did not have this features and the default for NET 3.5 SP1 was Full.
  • In addition to redist deployment, we also added support for web download which did not exist in Beta 1. Your app can now chain-install NET4 (Client Profile or Full) from the Microsoft download site.
  • Much improved NGEN speed on multi-core machines by compiling on each core/processor concurrently. See more here. (Note: this also existed in Beta1)

What is new in Visual Studio 2010 for NET4 Client Profile

  • We changed many of the Visual Studio 2010 project templates to target NET4 Client Profile by default. See below.
  • The Visual Studio 2010 Prerequisites dialog (e.g. when you click ‘Publish’ in the property page in Windows projects) automatically selects the correct profile (Client Profile or Full) depending on your project target.
  • The Visual Studio 2010 “Setup and Deployment” project selects the NET4 Client Profile prerequisite by default.
  • We are considering making the NET4 Client Profile the Framework that will be distributed on Windows Update to desktops, thus making the Client Profile ubiquitous (Note: this plan is not final and could change)

How to use Client Profile in Visual Studio 2010

Visual Studio 2008 introduced multi-targeting for application projects to target 2.0 and 3.x versions of the .NET Framework.
Visual Studio 2010 has improved multi-targeting in order to allow developers to easily target the new NET4 Client Profile. As a matter of fact, starting in Beta2 many of the client projects are targeting the NET4 Client Profile by default.

Projects that target NET4 Client Profile by default

These projects are now target the NET4 Client Profile by default:
Windows Project (C# and VB)
- WPF Application
- WPF Browser Application
- WPF Custom Control Library
- WPF User Control Library
- Windows Forms Application
- Windows Forms Control Library
- Console Application
- Empty Project
- Window Service

Visual F#
- F# Application
- F# Tutorial

Workflow (C# & VB)
- Activity Designer Library
- Activity Library
- Workflow Console Application

WCF (C# & VB)
-
WCF  Service Library

Office 2007 & 2010 templates (C# & VB)
-
All Projects

All other projects, including Class Library, target the Full Framework by default.
Mixed-target scenarios using Class Library may provide build errors, read more here.

How to retarget your project

To change targeting of your project, open the project properties, select the "Application" page, and change the “Target framework” drop-down.

C# project example:

image

VB project example (Project Properties > Compile tab > “Advanced Compile Options…”):

image

Note that if you right-click the project and select “Add References…”, the dialog shows only the .NET Framework assemblies that are part of the selected profile. This is accomplished by using reference assemblies (metadata-only versions of assemblies). The .NET Framework 4 Client Profile Reference Assemblies are located in:
  %programfiles%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client

At compile time, the reference assemblies are matched up against the known "Client List" assemblies that are included in the Client Profile. If a project targeting the Client Profile has a reference to a .NET assembly that is not included in the "Client List", Visual Studio displays compile-time errors in the Error List.

How to change targeting for other projects

Some other VS 2010 projects such as Managed C++ (Visual C++/CLR) still target the Full Framework by default. VS 2010 unfortunately does not provide UI to change the targeting.

Fortunately, you can still edit the project file manually in order to change the profile targeting. To do so:

  1. Right click “Unload Project”
  2. Right-Click “Edit <project_name>”
  3. Set the appropriate project property to target Client Profile. e.g.
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
  4. Right click “Reload Project”

In addition, for these projects, notice that VS does not create an <app.config> file for your project.
If your project does not add references or access assemblies that are included in the Full Framework but are not part of the Client Profile, there is nothing to worry about. Your app will run on machines with either NET4 Client Profile or Full Framework just fine.
Otherwise, if you do access assemblies from the Full Framework, you should add <app.config> to indicate to CLR not to load your app if it is launched on the NET4 Client Profile. E.g. add this

<?xml version="1.0"?>
<configuration>
   
<startup>
             
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
   
</startup>
</configuration>

If you don’t do so, your app may crash at random when it needs to load the assemblies that are missing from the Client Profile.

Deployment

The project Publish property page allows you to select the prerequisite needed for your ClickOnce deployment. In Beta2, VS2010 automatically selects the correct profile (Client Profile or Full) depending on your primary project target.

image

Setup and Deployment Projects

The same prerequisite dialog from above appears when you create “Setup and Deployment” (under “Add New Project”/“Other Project Types”). The NET4 Client Profile prerequisite entry is checked by default in this case.

image

image

If you create a new “Visual Studio Installer” setup project (under “Setup and Deployment“) and add the output of your NET4 Client Profile to it (do: Right-Click ->“Add”-> “Project Output…”’ select “Primary output”) , VS2010 adds a new “Launch Condition”. (Right-click on your new Setup project and then do “View->Launch Conditions”)
By default VS2010 will add NET4 Client Profile as a launch condition.
Note that a Beta2 bug still shows the Full Framework as the default launch condition; you can and should use the drop-down box to change it.
What this means is that once all prerequisites are installed and before the main installation launches, setup checks whether all the launch conditions are met. If not, setup blocks and displays an error message.

image

image

Important notes:

  • When you create new projects in VS2010, the “New Project” dialog does not indicate if the new project you are about to create is targeting Client Profile or Full. It is always a good idea to go to the project Properties above and confirm that you have the target framework you expected.
  • If you change the project to target the Full Framework, VS will add a configuration file (<app.config>) that declares the application as a "Full" application.
    image 
    This enables the CLR loader to block any NET4 apps that target “Full on machines that only have the Client Profile. In this case, the CLR prompts the user to install NET4 full. For example, you may see this dialog:

    Note that in NET4 Beta1 and NET3.5 SP1 Client Profile if the <app.config> was missing the CLR the assumption was that you targeted the Full Framework. This is now reversed.
  • You may encounter mixed-target scenarios: for example, when your Client Profile app adds a reference to a Class Library that is targeting the Full Framework (which it targets by default). You should be able to successfully build such solutions, as long as the Class Library does not use references to assemblies that only exist in the Full Framework. If it does, you may get warning/errors that are not completely clear.
    For example you may see an error in your Client Profile app saying:
    ”The type or namespace name 'ClassLibrary1' could not be found (are you missing a using directive or an assembly reference?)”

    This error is not clear because the class library exists and can be compiled when it is compiled by itself. However, when MSBuild tries to resolve the transitive closure of the Client Profile project, it cannot find the Full Framework assembly that is referenced by the Class Library. In this case it is better to look at the generated warnings which are more informative:
    ”The referenced assembly "ClassLibrary1.dll" could not be resolved because it has a dependency on "…<some assembly only available in Full Framework>…” which is not in the currently targeted
  • In general, it is always good practice to check the targeting of all projects in your solution to make sure they are what you intended. Remember that Client Profile apps will always run on Full Framework, but not the other way around.

What components are new in NET4 Client Profile Beta2?

In order to enable most (if not all) client apps to only require the NET4 Client Profile, in Beta2 we added some additional functionality. The main components/features that were included in the Full Framework in Beta1 and moved to the NET4 Client Profile Beta2 are:

    1. Speech
    2. Network and other performance counters
    3. Workflow 4.0 features
    4. Directory services components
    5. WMI Instrumentations components
    6. VB6 compatibility components
    7. Visual Basic Compiler
    8. Spell Checker and Hyphenation functionality required for WPF RichTextBox
    9. Created a new System.Web.ApplicationServices.dll assembly and moved certain types from System.Web.dll into it
    10. New WPF 4.0 Text stack to improve text clarity (new to NET4 in Beta2)
    11. Location APIs for Windows 7

In general, other than ASP.Net, tools (like MSbuild, Web admin tools) and legacy components that are becoming deprecated (e.g. Workflow 3.0, Oracle data client) almost everything else is now included in Client Profile in Beta2.

Enhancements in NET4 Client Profile vs. NET 3.5 SP1 Client Profile

Although the concept of a Client Profile is not new and was introduced in .NET Framework 3.5 SP1, the NET4 Client Profile contains important improvements:

 

.NET Framework 4 Client Profile

.NET Framework 3.5 SP1 Client Profile

Supported OS

Supported on all platforms and  OS's that are supported by the .NET Framework (excluding IA64 and the Server Core role in W2K8)

Supported only on Windows XP 32-bit machines that did not have any .NET Framework version installed.

(Client Profile setup silently installs the full 3.5 SP1 Framework otherwise)

Redistributable

Supports redistributable as well as web download

Supports web download only

Add Remove Programs entries

The full Framework comprises the Client Profile and another part called “Extended”. Thus it has two entries in the  Add/Remove Programs dialog (or Programs and Features window).

To remove (or repair) the Full Framework you must remove the Extended part first, then the Client part.

If you installed the Full Framework, you can switch to the Client Profile by simply removing “Extended” from Add/Remove Programs.

Single entry in Add Remove Programs

Visual Studio

Improved support for Client Profile targeting in Visual Studio 2010.

By default many Visual Studio 2010 Beta2 Client project target the NET4 Client Profile.

Single checkbox in Visual Studio 2008 Service Pack 1 “Application” Project properties for .NET Framework 3.5 projects. Client Profile support unavailable in out-of-the-box VS 2008.

Features

Includes new .NET 4  features (such as Managed Extensibility Framework (MEF), C# 4 Dynamic Keyword, etc) as well as features previously included in NET 3.5 SP1 Full (Speech, WPF Spell Check, etc)

Subset of features in .NET 3.5 SP1 Full

 

What’s in and what’s not included in the Client Profile?

Features

Full Framework

Client Profile

Common Language Runtime

   

Can be installed side-by-side with older versions of the Framework

In-process side by side support

Improved COM interop

     

Innovations in the Visual Basic and C# languages

   

statement lambdas

implicit line continuations

dynamic dispatch

named/optional parameters

     

Base Class Library Improvements

   

Managed Extensibility Framework

Additional core data structures

I/O Improvements

     

Parallel Computing Innovations

   

Task Parallel Library (TPL)

Parallel LINQ (PLINQ)

     

ADO.NET

   

REST-based exposure of relational data

Entity Framework, LINQ to Entities

SqlClient, OLEDB, ODBC Managed Providers

XML, LINQ to XML

OracleClient

x

LINQ to SQL

Runtime design libraries for Entity Framework and ADO.NET Data Services

x

     

ASP.NET Innovations

x

     

ASP.NET AJAX Improvements

x

     

XAML Parser

   

Faster

More extensibility during XamlReader.Load and XamlWriter.Save

Ability to use generics               

Better References by Name

     

Windows Presentation Foundation

   

New line-of-business controls including charting control, smart edit, data grid, and others that improve the experience for developers who build data centric applications

Support in for Windows 7 multi-touch, ribbon controls, and taskbar extensibility features

Added support in WPF for Surface 2.0 SDK

     

Windows Communications Foundation

   

WCF Client Component

Service discovery

Router service

Simplified configuration

Improved queuing

REST support

Improved performance

WCF Client Component

     

Windows Workflow Foundation

   

Improved activity programming model

Improved designer experience

New flowchart modeling style

Expanded activity palette

Workflow-rules integration

x

New message correlation features

Significant performance gains for WF-based workflows

WF3 and WF3.5 in .NET 4

    x

 

 

 

Miscellaneous

 

 

Speech support

Various perf counters

MSBuild support

x

Visual Basic compiler and other compilers

  Full Support
 Partial Support
X    no support

Where can I get the NET4 Client Profile?

You can get .NET Framework 4 by click on “Download the Beta” from this site: http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx

Redist vs. Web Download:

Web Download: For online scenarios, your application setup can chain-install the NET4 Framework from the Microsoft Download Center (or direct install by navigating to the download page).

When you use a web download, the .NET web bootstrapper is launched. The bootstrapper can determine your CPU architecture, locale, and components already existing on the machine, and can install only the components that are required. This is also known as ‘homesite’ deployment.

The .NET web bootstrapper also chain-installs the correct .NET Framework 4 Language Pack if your machine has a non-English locale.

Redist: For offline scenarios, you can also re-distribute (“redist”) the NET4 Framework on your own media (e.g. DVD) also known as ‘samesite’ deployment.

Install Flavors:

You can install the following flavors of the .Net Framework:

(The listed sizes are the package size, the space required on disk will be larger)

  1. dotNetFx40_Client_x86.exe (~30.91 MB): This is the Client Profile SKU that you could use to install on any supported 32-bit OS. You should redist on your own media. Choose this only if all your users are running 32 bit OS.
  2. dotNetFx40_Client_x86_x64.exe (~47.16 MB): This is the Client Profile SKU that you must install on any supported 64-bit OS. This will also install on any supported 32-bit OS. Your app could run in WOW64 if it was compiled w/ "32-bit" flag or as 64-bit if you compile with "AnyCPU" or "64-bit" flags.
    If you are redistributing the Framework with your application you most likely want to redist this package as it will be install on both 32 and 64 bit OS’s.
  3. dotNetFx40_Full_x86.exe (~37.71 mb): This is the Full Framework SKU that you could use to install on any supported 32-bit OS.
  4. dotNetFx40_Full_x86_x64.exe (~54.59 MB): This is the Full Framework SKU that you must install on any supported 64-bit OS. This will also install on any supported 32-bit OS.
  5. dotNetFx40_Full_x86_ia64.exe (~56.4 MB): This is the Full Framework SKU that you must install on IA64 OS. Client profile is not supported for IA64.
    (Even though technically you can remove “NET 4 Extended” in “Add/Remove Programs” and remain with Client Profile, it is not recommended that you do so. WPF is not even installed on IA64)
  6. NET 4 Beta 2 Web Bootstrapper: This is what you want to install if you need NET4 Full and you are online.
  7. NET 4 Client Profile Beta 2 Web Bootstrapper: This is what you want to install if you need NET4 Client Profile and you are online.

Note that above sizes are for ‘redist’ packages. With the Web installer the download size will likely be smaller since some of the components that are needed for NET4 may be already on your machine (e.g. rgb9rast.msi).

Feedback:

Please provide us with feedback. We really would love to know:

  • Does the NET4 Client Profile currently contain the right features set?
  • What functionality should be removed from or added to the NET4 Client Profile?
  • How easy it is to use in Visual Studio 2010?
  • Any other feedback?

Notes and caveats

  • Redistributable package size for the Client Profile is not final. Expect to see a smaller size by RTM.
  • Note that each setup package file name includes the word “Client” or “Full” to differentiate between the two packages. (e.g. dotNetFx40_Client_x86.exe, dotNetFx40_Full_x86.exe)
  • Setup may require a reboot, depending on the OS and currently running programs during installation.
  • We are still tweaking what should be in Client Profile vs. Full Framework, so there may be changes by RTM.
  • Support for the Client Profile Configuration Designer is not available in Beta 2 and likely will not be available before RTM.

Related blogs

Posted by jgoldb | 0 Comments

Memory Leaks in WPF based applications – Blog Update 2

We discovered few other potential memory leaks that WPF based application can encounter so I wanted to update my original Finding Memory Leaks in WPF-based applications blog and the sample in that blog with more info on these potential leaks.

As you may remember, I already updated my original blog once (see here), so this is the second update.

Please review the blog updates and use the suggested workarounds to avoid memory leaks in your WPF application. 
The new leaks that got updated are items 8-11:

8.  CMilChannel leaks if initial HWND destroyed on XP
9.  ShutdownListener leaked for each thread using Binding
10. Create and Destroy WriteableBitmap on XP in HW
11. SW Viewport 3D w/ VisualBrush, WB, etc. leaks on XP

Posted by jgoldb | 0 Comments

.NET Framework 4 Client Profile - Introduction

Introduction

Hopefully folks have seen Soma’s and Jason Zander’s blogs announcing the availability of Beta 1 of Visual Studio 2010 and .NET Framework 4.
In .NET Framework 4 we introduced a streamlined subset and more compact version of the .NET Framework called the Microsoft .NET Framework 4 Client Profile. The goal of the Client Profile is to improve the deployment size, time, reliability and overall deployment experience for client application users.

The Client Profile contains the functionality that most common desktop client applications (including Windows Forms and WPF applications) would need, so we expect that many client application developers will use it. This will improve the overall application deployment experience when the application requires .NET Framework 4 to be installed.

One of the most important improvement is that Microsoft .NET Framework 4 Client Profile is now supporting all platforms and OS's that are supported by the full Framework including Vista, XP, Win2k3, Win2k8, Windows7, x86/x64 (excluding IA64)

We still expect some applications to target the full .NET Framework 4 if they need to use features that are not included in the .NET Framework 4 Client Profile.

Client Profile in Visual Studio 2010

Visual Studio 2008 introduced multitargeting for application projects to target 2.0 and 3.x versions of the .NET Framework. Visual Studio 2010 has improved multi-targeting in order to allow developers to easily target the new .NET Framework 4 Client Profile.

In Beta 1, when you create a new Windows Forms or WPF application, it targets the full framework by default. To change to targeting to the Client Profile, open the project properties, select the "Application" page, and change the “Target Framework” drop-down to “.NET Framework 4.0 Client Profile.”

C# project example:

image

VB project example (Project Properties > Compile tab > “Advanced Compile Options…”):

image

Notice that if you right-click the project and select “Add References…”, the dialog will show only the .NET Framework assemblies that are part of the Client Profile. This is accomplished by using reference assemblies, metadata-only versions of assemblies. The .NET Framework 4 Client Profile Reference Assemblies are located in

%programfiles%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client

At compile time, the reference assemblies are matched up against the known "Client List" assemblies that are included in the Client Profile. If the project has a reference to a .NET assembly that is not included in the "Client List", Visual Studio will display compile-time errors in the Error List.

Similar to the .NET 3.5 Framework SP1 Client Profile, the project adds a configuration file (app.config) that will specifically declare the application as a "client" application. This declaration indicates to the CLR loader that you are trying to run a Client Profile application. Without the configuration file, the CLR loader thinks that you are trying to run full .NET 4, and if the machine only has the Client Profile installed, it prompts ebd-user to install the full .NET 4. [Note: this functionality is not available in Beta1.]

Enhancement in 4.0 Client Profile vs. 3.5 SP1 Client profile:

Although the concept of a Client Profile is not new and was introduced in .NET Framework 3.5 SP1, the 4.0 Client Profile contains important improvements:

 

.NET Framework 4 Client Profile

.NET Framework 3.5 SP1 Client Profile

Supported OS

Supported on all platforms and  OS's that are supported by the .NET Framework (excluding IA64 and Server Core role in W2K8)

Supported only on Windows XP 32-bit machines that did not have any .NET Framework version installed.

(Client Profile will install the full 3.5 SP1 Framework under the covers otherwise)

Redistributable

Supports redistributable as well as web download

Supports Web download only

Add Remove Programs entries

The full Framework comprises the Client Profile and another part called “Extended” thus it has two entries in the  Add Remove Programs dialog (or Programs and Features window).

To remove (or repair) the full Framework you must remove the Extended part first, then the Client part.

If you installed the full Framework, you can go to the Client Profile by removing “Extended” from Add/Remove Programs.

Single entry in Add Remove Programs

Visual Studio

Improved support for Client Profile targeting in Visual Studio 2010

 

Features

Includes new .NET 4  features (such as Managed Extensibility Framework (MEF), C# 4 Dynamic Keyword, etc)

 

What’s in and what’s not included in the Client Profile:

Features

full Framework

Client Profile

Common Language Runtime

   

Can be installed side-by-side with older versions of the Framework

In-process side by side support

Improved COM interop

     

Innovations in the Visual Basic and C# languages

   

statement lambdas

implicit line continuations

dynamic dispatch

named/optional parameters

     

Base Class Library Improvements

   

Managed Extensibility Framework

Additional core data structures

I/O Improvements

     

Parallel Computing Innovations

   

Task Parallel Library (TPL)

Parallel LINQ (PLINQ)

     

ADO.NET

   

REST-based exposure of relational data

Entity Framework, LINQ to Entities

SqlClient, OLEDB, ODBC Managed Providers

XML, LINQ to XML

OracleClient

 

LINQ to SQL

 

Runtime design libraries for Entity Framework and ADO.NET Data Services

 
     

ASP.NET Innovations

 
     

ASP.NET AJAX Improvements

 
     

XAML Parser

   

Faster

More extensibility during XamlReader.Load and XamlWriter.Save

Ability to use generics               

Better References by Name

     

Windows Communications Foundation

   

WCF Client Component

WCF Workflow Services

 

Service discovery

 

Router service

 

Simplified configuration

Improved queuing

REST support

Improved performance

     

Windows Presentation Foundation

   

New line-of-business controls including charting control, smart edit, data grid, and others that improve the experience for developers who build data centric applications

Support in for Windows 7 multi-touch, ribbon controls, and taskbar extensibility features

Added support in WPF for Surface 2.0 SDK

     

Windows Workflow Foundation

   

Improved activity programming model

 

Improved designer experience

 

New flowchart modeling style

 

Expanded activity palette

 

Workflow-rules integration

 

New message correlation features

 

Significant performance gains for WF-based workflows

 

Miscellaneous

 

 

Speech support

 

Various perf counters

 

MSBuild support

 

Visual Basic compiler and other compilers

 

• Full Support

Partial Support

 

Download and feedback

Please download the Client Profile from the download site here and provide us with feedback. We really would love to know:

  • What do you feel should be the size of the Client Profile?
  • Does it currently contain the right features set? What functionality is missing?
  • To reduce size, what functionality should be removed?
  • How easy it is to use in Visual Studio 2010?
  • Any other feedback?

Notes and caveats:

  • Redistributable package size for the Client Profile is not final (it is currently at ~34MB). Expect to see a smaller size by RTM. Web installer is also not supported in Beta 1
  • Note that the setup package file name includes the word “Client” vs. “Full” to differentiate between the two packages. (e.g. dotNetFx40_Client_x86.exe, dotNetFx40_Full_x86.exe)
  • Setup may require a reboot, depending on the OS and currently running programs during installation.
  • No bootstrapper package is available yet, so you will not find the .NET Framework 4 Client Profile in Visual Studio 2010's "Prerequisites" dialog in the project's "Publish" property tab.
  • We are still tweaking what should be included in Client Profile vs. full Framework, so it is very likely to change before RTM.
  • Support for the Client Profile Configuration Designer is not available in Beta 1 and likely will not be available before RTM.
Posted by jgoldb | 8 Comments

Great Charles Petzold post

Check out Charles Petzold blog.

It discusses and provide examples on how you in WPF you don’t need to re-create the entire render data just to handle property changes, and thus improve perf.

Posted by jgoldb | 0 Comments

Improving Microsoft DataGrid sorting performance - Part 3

As it was announced at the PDC 2008 keynote, the Microsoft WPF DataGrid V1 is now released and available with the WPF Toolkit on Codeplex.

I wanted to update my CustomSort sample to improve WPF DataGrid sort performance from here to use the released version of the WPF Toolkit.

Enjoy.

Posted by jgoldb | 1 Comments

Attachment(s): DataGridSort3.zip

Fixes to WpfPerf Performance Profiling Tool

Some folks reported issues with x64 & with x86 on non-US PCs with our first post.
On 10/9/2008 we posted an update.  These issues should be fixed now.

You are welcome to download from: http://windowsclient.net/wpf/perf/wpf-perf-tool.aspx

Posted by jgoldb | 3 Comments

ETW Event Tracing in WPF

Event Tracing for Windows (ETW) provides application developers the ability to start and stop event tracing sessions, instrument an application to provide trace events, and consume trace events.

In addition to Windows itself, WPF also emits an array of interesting events that can be used to track the execution of an application at the framework level.

Mike Cook wrote a great document that explain the various ETW events emitted by WPF.

Check out the this documentation here.

You are encouraged to use these events to measure and analyze your WPF application performance.

The WpfPerf tool for example, use these events extensively. In addition, the WPF team is also using ETW in its automated tests to analyze WPF performance and catch regressions.

Attached is also a sample that demonstrates how you can consume one of these events (UceNotifyPresent event) to measure frame-rate (aka FPS , Frame-per-Second) in a WPF application.

The sample animates a rectangle and outputs the FPS to a command window . It is writing to a command window and not to the main app window so that it will not affect the real FPS.
image 
You should expect to see frame-rate tied to the refresh rate of your monitor.
Special thanks to Mike Cook and  TJ Hsiang who helped put this sample together.

Posted by jgoldb | 6 Comments

Attachment(s): FPSMeasurementSample.zip

Updated WPFPerf Performance Profiling Tools for WPF

The WPFPerf tool comprises of a suite of performance profiling tools that allow you to analyze the run-time behavior of your WPF application and point to potential performance bottlenecks.

We now added some new functionality as well as given the tool a major facelift.
Below are highlights for some of the exciting improvements that are included in this update.
More details and download link is available here.
Most of the concepts on how to use the tool remain the same so you can still refer to the existing documentation for the tool here to learn more.  The tool should work on all 3.x version of .Net.

Note: some folks reported issues when installing on none-US machines. Until this is investigated, please install only on US  machine using the default local settings.

A) Much improved “Visual Profiler” tool:
image 

The Visual Profile tool now provides:

1) Search: provides the ability to search element in the application’s Element Tree.
image

2) Hotpath: Allows you to Right Click / Expand Hotpath on an Element Tree, the tree will expand to show the element in the sub-tree that consumes the most amount of CPU in that sub-tree.

3) Elements CPU Usage: As user expands the Element Tree (e.g. by using the Hotpath feature from above), elements that (Exclusively) consumes CPU time are highlighted in Red. The intensity of the Red highlighting corresponds to the percentage of CPU usage.

image

4) Tinting the Target Application : Using the Overlay Window button, you can view the Selected and Hotpath sub-tree elements in their target application.
If the Overlay Window button is depressed, then:

  • Selecting an element in Visual Profiler’s Element Tree will draw a yellow rectangle on that same element in the target application.
  • Hotpath elements are tinted in Red in the target application. The intensity of the Red tinting in the target application corresponds to the percentage of CPU usage.

Here is an example of how target application may look:
image

Note: Enabling this feature will slow the target application performance. In addition, tinting the target application uses Layered Windows. It is recommended that users follow this blog to make to obtain latest QFEs (or use XP Sp3 or Vista Sp1)

5) Live Preview: If the “Live Preview” is enabled, then in a live representation of the selected Element sub-tree is drawn on the bottom left. Otherwise a static image of the sub-tree is displayed.
In both cases, the image will change if another Tree Element is selected.

Note: Enabling this feature will slow the target application performance.

6) Splitter control: Allows user to adjust the various display areas (E.g. the Element Tree & Element Information areas)

7) Graph Duration Slider: Allow user to change the amount of history data collected.

8) Expander controls: Allow user to remove un-wanted clutter from the screen

9) Element Tree View: Using the View menu you can control what information is displayed on the each node in the Element Tree and remove unwanted clutter.
clip_image010

B) Much improved “Perforator” tool:
image 

The Perforator tool now provides:

1. Improved UX : More intuitive and richer UX.

2. History Data:

  • History Graphs of Frames-Per-Second, Direct Rectangles Addition Rate, HW and SW IRT count and Video Memory Usage.
  • Graph Duration slider to change the amount of history data.
  • Capture Start/Pause button to allow pause and re-capture of data.
    The History Graph value axis (Y-Axis) is now auto-adjusting.

3. Detect SW rendered Bitmap Effects: Checkbox added to tint the target application elements that use SW rendered legacy Bitmap Effects.

In below example, the top button is decorated with OuterGlowEffect Bitmap Effect. Since this effect is not HW accelerated the Button is tinted in Red.

The bottom Button is decorated with DropShadow Bitmap Effect which is HW accelerated (DropShadow is now HW accelerated in .Net 3.5 Sp1), and therefore is not tinted with Red.
image 
Known limitations:
A) You must force the target elements to redraw itself after you enabled the checkbox for you to see the red tint. E.g. hover over with the mouse, if it is standard button.
B) You still need to launch Perforator before you launch your app.

C) New tool: String Allocation Profiler
image
We added a new tool to WPFPerf called “String Allocation Profiler”
The tool enables users to view all the strings and their sizes which were allocated by the application from the time the application started till the time it closed.

To use this tool:
1. Click on “Action / Lunch Process…” to launch the target application.
Notice that WpfPerf says “Profiling…” on the status barclip_image002[4]
2. Click around your application and when done close it.
Notice that WpfPerf says “Processing Profile Data…” on the status bar
clip_image004
3. When done, WpfPerf displays the application method tree and for each method it shows the Inclusive and Exclusive # of strings allocations and their sizes.
4. You can drill down the application Method Stack Tree to view all the strings your application allocated in a specific method sub-tree.
5. Search: If you know the string names you can also search for them and find the methods that allocated them.
6. Using the “Action/Save String Allocation Log” and “Action / Save String Allocation Log” menu, you can save and open a view allocation logs at a later point.
clip_image006
Notes:
a) The tool display strings allocated directly by the application (in code and XAML) as well as strings allocated by the CLR and WPF framework.
b) The tool have affect on the performance of you application while it monitors string allocations.

D) ETW Event Tracing tool:
Some bugs fixed, and new detailed documentation for the WPF ETW events is now available. See more here.

E) General improvements:
1) Numerous bug fixes
2) Now you can attach and profile XBAPs in addition to Standalone WPF apps
3) Improved “Add Tool” dialog. 
    It now allows user to select more than one tool at a time.
clip_image002[6]
4) UI improvements to the “Select Process” dialog.
    This allows user to select the target application to profile.
clip_image004[5]
5) UI improvements to the “Launch Process” dialog.
clip_image006[5]

F) Know issues and Caveats:

  1. General:
    Try to avoid using more than one tool (e.g. Visual profiler & Perforator) at the same time to profile the same app as it will decrease the application performance.
  2. Perforator/ Detect SW rendered Bitmap Effects:
    When you set “Detect SW rendered Bitmap Effects”, in order for the Red tint to show, you must force the target elements to redraw itself.
  3. Perforator/ Overlay Window:
    Tinting the target application uses Layered Windows. It is recommended that users follow this blog to make to obtain latest QFEs (or use XP Sp3 or Vista Sp1)
  4. Perforator/ Live Preview:
    Live Preview uses Visual brush, so if you also use Perforator to profile the same app, you may see that the HW IRT count increases by 1.
  5. Perforator/Visual profiler
    You can attach to an XBAP (by attaching to PresentationHost.exe), but you may not able to launch an XBAP.
  6. Perforator/Visual profiler
    You must launch Perforator before you launch your app.

Please enjoy the tool and tell us what you think and what needs improvement.

Posted by jgoldb | 15 Comments

Improving Microsoft DataGrid CTP sorting performance - Part 2

In this blog I wrote how you can improve Microsoft DataGrid CTP by providing your own custom sort.  
As one of the comments suggested you can get even better performance by using delegates.
I have changed MySort code below and I now use delegates to avoid the switch comparison that was called on every compare during the QuickSort . I can now see additional ~50% speed gain during sort.

In my 300,000 rows DataGrid, before I saw sort speed decreased from almost 5 minutes to 2.4 seconds and now the String type columns (e.g. Name, Position) are sorted in 1.4 sec while the Integer type columns (e.g. Id) are now sorted in 400 ms!

   1:  public class MySort : IComparer
   2:  {
   3:        public delegate int TwoArgDelegate(Employee arg1, Employee arg2);
   4:        TwoArgDelegate myCompare;
   5:        public MySort(ListSortDirection direction, DataGridColumn column)
   6:        {
   7:                  int dir = (direction == ListSortDirection.Ascending) ? 1 : -1;
   8:                  //set a delegate to be called by IComparer.Compare
   9:                  switch ((string)column.Header)
  10:                  {
  11:                      case "Id":
  12:                          myCompare = (a, b) => { return a.Id.CompareTo(b.Id) * dir; };
  13:                          break;
  14:                      case "Name":
  15:                          myCompare = (a, b) => { return a.Name.CompareTo(b.Name) * dir; };
  16:                          break;
  17:                      case "Position":
  18:                          myCompare = (a, b) => { return a.Position.CompareTo(b.Position) * dir; };
  19:                          break;
  20:                      case "Tel":
  21:                          myCompare = (a, b) => { return a.Telephone.CompareTo(b.Telephone) * dir; };
  22:                          break;
  23:                      case "Email":
  24:                          myCompare = (a, b) => { return a.Email.CompareTo(b.Email) * dir; };
  25:                          break;
  26:                      case "Enabled":
  27:                          myCompare = (a, b) => { return a.Enabled.CompareTo(b.Enabled) * dir; };
  28:                          break;
  29:                      case "City":
  30:                          myCompare = (a, b) => { return a.City.CompareTo(b.City) * dir; };
  31:                          break;
  32:                      case "Country":
  33:                          myCompare = (a, b) => { return a.Country.CompareTo(b.Country) * dir; };
  34:                          break;
  35:                      default:
  36:                          myCompare = (a, b) => { return 0; };
  37:                          break;
  38:                  }
  39:              }
  40:              int IComparer.Compare(object X, object Y)
  41:              {
  42:                  return myCompare((Employee)X, (Employee)Y);
  43:              }
  44:      }
  45:  }
Posted by jgoldb | 4 Comments

Attachment(s): DataGridSort2.zip

Improving Microsoft DataGrid CTP sorting performance

Summary:

As you may know Microsoft released a Community Tech Preview (CTP) of the DataGrid control. See the posting here.
Once you start using the DataGrid CTP, load many elements to it and you use the default, built-in sort (by simply clicking on the DataGrid column headers) you may notice that sorting can be very slow.
The reason is that the comparer that is built-in to the MS DataGrid knows nothing about your data type and currently use reflection which is very costly.

In this blog I wanted to point you to a simple approach that could significantly improve the sorting performance of your DataGrid.

Approach:

If you load many elements to the MS DataGrid and use the built-in sort which currently use reflection, you may find sorting to be very slow.

Fortunately, for many scenarios you can implement your IComparer and provide it in the CustomSort property. You could achieve significant performance gains by doing so, in my example I was able to achieve 100x speed improvement.

In my 300,000 rows DataGrid, sort speed decreased from almost 5 minutes to 2.4 seconds !
(The provided download only loads 6,000 rows, but you are welcome to change...)

image

Code:
public partial class Window1 : System.Windows.Window
{
    private bool UseCustomSort
    {
        get { return CustomSortCB.IsChecked == true; }
    }
 
    private void WPF_DataGrid_Sorting(object sender, DataGridSortingEventArgs e)
    {
        if (_stopwatch == null)
        {
            _stopwatch = new Stopwatch();
        }
        else
        {
            _stopwatch.Reset();
        }
 
        _stopwatch.Start();
        if (UseCustomSort)
        {
            e.Handled = true;   // prevent the built-in sort from sorting
            PerformCustomSort(e.Column);
            CustomSortingDone();
        }
        else
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, new NoArgDelegate(StandardSortingDone));
        }
    }
 
    private void StandardSortingDone()
    {
        _stopwatch.Stop();
        statusTextBlock1.Text = "Buit-in Sort: " + _stopwatch.ElapsedMilliseconds.ToString() + " msec";
    }
    private void CustomSortingDone()
    {
        _stopwatch.Stop();
        statusTextBlock2.Text = "Custom Sort: " + _stopwatch.ElapsedMilliseconds.ToString() + " msec";
    }
    private void PerformCustomSort(DataGridColumn column)
    {
 
        ListSortDirection direction = (column.SortDirection != ListSortDirection.Ascending) ? 
                                 ListSortDirection.Ascending : ListSortDirection.Descending;
        column.SortDirection = direction;
        ListCollectionView lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(WPF_DataGrid.ItemsSource);
        MySort mySort = new MySort(direction, column);
        lcv.CustomSort = mySort;  // provide our own sort
    }
 
    public class MySort : IComparer
    {
        public MySort(ListSortDirection direction, DataGridColumn column)
        {
            Direction = direction;
            Column = column;
        }
 
        public ListSortDirection Direction
        {
            get;
            private set;
        }
 
        public DataGridColumn Column
        {
            get;
            private set;
        }
 
        int StringCompare(string s1, string s2)
        {
            if (Direction == ListSortDirection.Ascending)
                return s1.CompareTo(s2);
            return s2.CompareTo(s1);
        }
 
        int IComparer.Compare(object X, object Y)
        {
            int int1, int2;
            string str1, str2;
            switch ((string)Column.Header)
            {
                case "Id":
                    int1 = ((Employee)(X)).Id;
                    int2 = ((Employee)(Y)).Id;
                    if (Direction == ListSortDirection.Ascending)
                        return int1.CompareTo(int2);
                    return int2.CompareTo(int1);
                case "Name":
                    str1 = ((Employee)X).Name;
                    str2 = ((Employee)Y).Name;
                    return StringCompare(str1, str2);
                // ... do same for other columns
     
              }
            return 0;
        }
    }
   private Stopwatch _stopwatch;
}

XAML Code:
<Window x:Class="DataGridSortDemo.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:local="clr-namespace:DataGridSortDemo"
    xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
    xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
    Title="Microsoft DataGrid Sort Example" Height="760" Width="850"
    >
    <Window.Resources>
        <local:Employees x:Key="employees" />
    </Window.Resources>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition MinHeight="25" Height="Auto"/>
      <RowDefinition MinHeight="3in" Height="*" />
      <RowDefinition Height="Auto" MinHeight="10" />
      <RowDefinition Height="Auto" MinHeight="10" />
      <RowDefinition Height="Auto" MinHeight="10" />
      <RowDefinition Height="Auto" MinHeight="10" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
 
 
    <dg:DataGrid x:Name="WPF_DataGrid" FontSize="12pt"
                 Grid.Row="1" Grid.Column="0"  Margin="10,2,10,2"
                 AutoGenerateColumns="False"
                 Sorting="WPF_DataGrid_Sorting"
                 ItemsSource="{StaticResource employees}"
              >
            
      <dg:DataGrid.Columns>
        <dg:DataGridTextColumn Width="Auto" Header="Id" DataFieldBinding="{Binding Path=Id}"></dg:DataGridTextColumn>
        <dg:DataGridTextColumn Width="Auto" Header="Name" DataFieldBinding="{Binding Path=Name}"></dg:DataGridTextColumn>
        <dg:DataGridTextColumn Width="Auto" Header="Position" DataFieldBinding="{Binding Path=Position}"></dg:DataGridTextColumn>
        <dg:DataGridTextColumn Width="Auto" Header="Tel" DataFieldBinding="{Binding Path=Telephone}"></dg:DataGridTextColumn>
        <dg:DataGridTextColumn Width="Auto" Header="Email" DataFieldBinding="{Binding Path=Email}"></dg:DataGridTextColumn>
        <dg:DataGridTextColumn Width="Auto" Header="Enabled" DataFieldBinding="{Binding Path=Enabled}"></dg:DataGridTextColumn>
        <dg:DataGridTextColumn Width="Auto" Header="City" DataFieldBinding="{Binding Path=City}"></dg:DataGridTextColumn>
        <dg:DataGridTextColumn Width="Auto" Header="Country" DataFieldBinding="{Binding Path=Country}"></dg:DataGridTextColumn>
     </dg:DataGrid.Columns>
    </dg:DataGrid>
 
    <TextBlock Grid.Row="2" Name="statusTextBlock1" Foreground="Red"
               FontSize="12pt" Text="" />
    <TextBlock Grid.Row="3" Grid.Column="0" Name="statusTextBlock2" Foreground="Green"
               FontSize="12pt"  Text=""  />
    <CheckBox  Name="CustomSortCB" FontWeight="Bold"  FontSize="12pt" Grid.Row="0" Grid.Column="0" Margin="10,6,6,6"
               Foreground="Blue">
      Use Custom Sort  [Check / Uncheck box, then Click on the DataGrid header to compare Sort performance]
    </CheckBox>
 
 
  </Grid>
</Window>
Caveats:

You can only use the CustomSort if your DataGrid is bound to an IList. You cannot use the CustomSort if you bound to an instance of IBindingList such as DataView. In this case the class that derives from ICollectionView is a BindingListCollectionView which does not have a custom sort property. The view in this case delegates the Sort logic to the underlying DataView which does not allow sort customization.

Posted by jgoldb | 9 Comments

Attachment(s): DataGridSort.zip

What’s new in WPF 3.5 SP1: Splash Screen to improve perceived startup perf

Summary:

To improve the perception of a more responsive startup experience many WPF applications added a Splash Screen to their startup.  The Splash Screen, which does not load WPF code shows as soon as possible and is displayed until the application main window is rendered.
Up until 3.5 Sp1 we pointed developers to sample code available on this blog.
In  the just released .Net 3.5 SP1 we added basic Splash Screen support and new APIs and we recommend that you take advantage of it. (See download locations below)

A Visual Studio 2008 Sp1 Item Template that makes adding a Splash Screen much easier is available on WPF Futures site on www.codeplex.com/wpf.

How to Use:

     Approach A:

The easiest way to add is by using VS 2008  SP1.
·  Create a new Standalone VB or C# WPF project in VS 2008 Sp1.  Verify “Target Framework” project property is “.Net Framework 3.5”

·   Add an image (your splash screen image) to the project (e.g. by drag and drop) 

·   Set the image BuildAction to SplashScreen

·   Do F5 ( Build+Run), splash screen should be shown.

·   To disable the Splash Screen image functionality you can either:

   o    Remove the “SplashScreen.png” image from the project, or

   o Set the splash image BuildAction to ‘None’.

image

Upon compile, the build (PresentationBuildTasks.dll) will generates below code in App.g.cs:

   1: SplashScreen splashScreen = new SplashScreen("Splashscreen1.png");
   2: splashScreen.Show(true);
   3: MyApp.App app = new MyApp.App();
   4: app.InitializeComponent();
   5: app.Run();

Note:  Above code will be generated in VS 2008 Sp1 only if the “Target Framework” project property is “.Net Framework 3.5”. Otherwise no code will be generated.

Approach B:

Install the Splash Screen Visual Studio 2008 Sp1 Item Template from the WPF Futures site.

·   Create a new Standalone VB or C# WPF project in VS 2008 Sp1.  Verify “Target Framework” project property is “.Net Framework 3.5”

·   In VS,  Right-Click on your Project and then select “Add / New Item… / Splash Screen (WPF)”.

·   Notice the new image BuildAction  is set to SplashScreen for you.

·   Do F5 (Build+Run), the default splash screen image that was installed with the template will be shown (you likely want to replace with your own Splash Screen image)

image

Approach C:

Another approach is to directly use the new public Splash Screen APIs. With this approach you can set the ‘BuildAction=Resource’.
For example you can call the following code:

   1: SplashScreen appSplash = new SplashScreen("Splashscreen1.png");
   2: appSplash.Show(false);
   3: //….do some work…
   4: appSplash.Close( TimeSpan.FromSeconds(0.3)); // Splash to fadeout in 300ms

The WPF Splash Screen APIs are defined as below:

   1: namespace System.Windows
   2: {
   3:     public class SplashScreen
   4:     {
   5:         public SplashScreen(string resourceName);
   6:         public SplashScreen(Assembly resourceAssembly, string resourceName);
   7:         public void Show(bool autoClose);
   8:         public void Close(TimeSpan fadeOutDuration);    
   9:     }
  10: }

public ApplicationSplashScreen(string resourceName)

Behavior

Constructor.  resourceName points to the embedded splash image

Exceptions

 none

public ApplicationSplashScreen(Assembly resourceAssembly, string resourceName)

Behavior

Constructor. resourceAssembly specify the assembly in which resources lives resourceName points to the embedded splash image

Exceptions

 none

public void Show(bool autoClose);

Behavior

Constructor. Shows the splash image.

If autoClose is true, the code uses the dispatcher to queue an item at Idle priority, enabling the Splash screen to start fading out using the default fadeOutDuration (300 msec) after the application first renders. 

If autoClose is false, the app is responsible to call Close(fadeOutDuration), in this case the splash screen fades out using the provided fadeOutDuration.

Exceptions

 IOException if resource provided in constructor not found in app assembly

public void Close(TimeSpan fadeOutDuration)

Behavior

Closes the splash window. 

fadeOutDuration is the time for splash screen to fade out. If autoClose is true, WPF will close the window and use a 300 msec as the default fadeOutDuration.

Exceptions

none

Caveats:

It is important to understand that the Splash Screen has the following limitations:
·         It does not actually improve application cold startup time.
·         Cannot display sequence of splash images or animation.
·         Does not support for animated GIFs
·         Does not support earlier versions of VS (earlier than VS2008 Sp1). You should still be able to use the APIs (e.g. Approach C)

·         Does not support XBAPs (XBAPs already have their own improved coldstart progress page in  .Net 3.5 Sp1)
·         Does not have  XAML support for setting splash screen image
·         Expression Blend does not provide UI to  set the SplashScreen build action

.Net 3.5 SP1 Download locations:

Content

Links

Visual Studio 2008 Express Editions with Service Pack 1 (Bootstrappers)

http://go.microsoft.com/fwlink/?LinkId=123679

Visual Studio 2008 Express Editions with Service Pack 1 (iso)

http://go.microsoft.com/fwlink/?LinkId=123680

Visual Studio 2008 Service Pack 1 (Bootstrapper)

http://go.microsoft.com/fwlink/?LinkId=122094

Visual Studio 2008 Service Pack 1 (iso)

http://go.microsoft.com/fwlink/?LinkId=122095

Visual Studio  Team System 2008 Team Foundation Server Service Pack 1

http://go.microsoft.com/fwlink/?LinkId=124829

.NET Framework 3.5 Service Pack 1

http://go.microsoft.com/fwlink/?LinkId=124150

 

Posted by jgoldb | 12 Comments

Improve WPF application startup using ClickOnce On-Demand Download

In this blog (see item 11.) we discussed the fact that ClickOnce can have a significant effect on application start app time.

For standalone applications (both WPF and Winform apps) if you use the default settings in Visual Studio, ClickOnce will access the site-of-origin server (e.g. company network or internet) to check for a newer version before the application start. As expected, this will slow down the overall application startup. You can consider modifying this default setting to check for a new version after the application starts.

In the XBAP case this is not configurable. ClickOnce will always check the deployment site (site-of-origin) for updates before the XBAP starts.

In certain scenarios, you can consider using the ClickOnce Deployment APIs to download a smaller part of your application (for example, code required only for the first screen of the application) and download the rest of your app modules at a later stage, in the background, as they are needed. If your app is large, this could significantly improve your application startup performance the first time it runs.

It is also very possible that your end-user will not use certain portions of the application, so if you can identify what they are and avoid downloading them it could provide a big win.

Below I have a sample XBAP that shows how you can use the ClickOnce Deployment APIs to achieve this. Note that this approach works both for Standalone and XBAPs applications.

Although the overall size of my sample is 13MB in size, the application downloads and displays relatively quickly since at first we only download the main app module which is only 9KB in size.

The large image resources (~13MB) are contained in a separate module (SimpleOnDemandLibraray.dll) and are not downloaded at startup. SimpleOnDemandLibraray.dll is downloaded in the background from the XBAP site-of-origin only when user clicks on the button.

After launching XBAP this is what is shown:

OnDemand1 

Only when users click on the button the ~13MB module (SimpleOnDemandLibraray.dll) which contains the image resources downloads in the background.
Your app could display a fancier progress UX then mine…:)
OnDemand2
Sometime later, when download completes the image shows as below:OnDemand3

To enable this you need specifcy that SimpleOnDemandLibraray.dll is an optional component.
You can do this in Visual Studio in the Properties/Publish/ Application Files property page like here:

OnDemand4

The code is very simple and looks like this:

private void InvokeDownloadGroup(object sender, RoutedEventArgs e)
{
     try
     {
        Status.Visibility = Visibility.Visible;      
        ApplicationDeployment thisApp = ApplicationDeployment.CurrentDeployment;
        thisApp.DownloadFileGroupCompleted +=
                  new DownloadFileGroupCompletedEventHandler(DownloadFileGroupCompleted);
        thisApp.DownloadFileGroupAsync("OnDemandGroup1"); // Start the download
      }
      catch (Exception exp)
      {
        Status.Visibility = Visibility.Collapsed;
        onDemandResult.Content = "Failed: " + exp.Message.ToString();
      }
}
 
// Called when download completes
void DownloadFileGroupCompleted(object sender, DownloadFileGroupCompletedEventArgs e)
{
     Status.Visibility = Visibility.Collapsed;
     // Show an image from the downloaded group to demonstrate it is available from this 
     // event forward...
     Image myImage = new Image();
     BitmapImage myBitmapImage = new BitmapImage();
     myBitmapImage.BeginInit();
     myBitmapImage.UriSource = 
                new Uri("pack://application:,,,/SimpleOnDemandLibrary;component/LargeImage.JPG");
     myBitmapImage.EndInit();
     myImage.Source = myBitmapImage;
     MyParent.Children.Add(myImage);
}

Special thanks to Matt Galbraith who helped with this sample.

More info on the ClickOnce Deployment API is here: http://msdn.microsoft.com/en-us/library/ak58kz04(VS.80).aspx

To download XBAP sample (.zip) click here.

Posted by jgoldb | 1 Comments

What’s New for Performance in WPF in .Net 3.5 SP1

As you know the .NET Framework 3.5 Service Pack 1 Beta download is now available. There are many improvements in this release that we are very excited about. Scott Guthrie blogged about these improvements here and so did Tim Sneath. In this blog I want to specifically focus and provide more details on the performance improvements coming in WPF.

Graphics Improvements

Significantly improved BitmapEffects performance

  • Up until .Net 3.5 SP1, all BitmapEffects were rendered in Software, now the Blur and DropShadow BitmapEffects are Hardware Accelerated and rendered by the GPU.
    We measured ~5x CPU, frame rate and video memory usage gains in by using the GPU for some scenarios.
  • It is important to note that the other built-in effects, (namely OuterGlow, Bevel, Emboss) continue to render in Software and should be avoided.
  • “Most’’ apps see gains simply by upgrading to .Net 3.5 SP1, without re-compile.
  • No gains will be seen after upgrade if the app uses effects that are:
    • Are used in an EffectGroup
    • Have too large a blur radius
    • Aren’t running on a Tier-2 video card (DX Ver. >= 9.0)
  • New Effects (now called BlurEffect, DropShadowEffect ) are introduced and these will always be Hardware Accelerated.
  • It is recommended that you do not use old Effects: BevelBitmapEffect, BlurBitmapEffect, DropShadowBitmapEffect, BevelBitmapEffect, EmbossBitmapEffect, OuterGlowBitmapEffect as these are being marked obsolete. Instead use the new effects.
  • Note that the legacy Effects extensibility mechanism has not been accelerated

New Effect Extensibility

  • We added support to Hardware Accelerated HLSL shaders with the new ShaderEffect class
  • These extensible effects can expose dependency properties that can be written/read to/from, animated and data- bound just like any other DPs
  • Currently we support full-trust only
  • Support "multi-input" effects where multiple UIElements can be provided to and manipulated by an Effect.  (included only in final RTM bits)
  • See more details in Greg Schechter’s blog.

Improved DirectX Integration

  • New D3DImage class, enabled developer to overlay or blend Direct3D content interchangeably with WPF content (e.g. use the Direct3D surface as a brush for WPF content, or apply it as a texture within a WPF 3D scene ) without any major performance impact.
  • Note: this feature will only be available in the RTM bits

Improvements to WriteableBitmap

  • WriteableBitmap is a mechanism for drawing & updating a system-memory bitmap to the screen on a per-frame basis.
  • This feature was available before, but before we allocated a new bitmap with every frame update, which made it too slow for some scenarios.
  • The new implementation is now much more efficient; it is synchronized with UI changes and has constant memory usage. This enables new scenarios such as, paint programs, fractal renderers, scatter plots, music visualization and other complex geometries that were not possible before.
  • Note: it is recommended that you use BGR32 or pBGRA32 pixel formats when possible. Other formats must run through a format converter each frame, which reduces perf.

Improved Text Performance

  • We improved our glyph management infrastructure which provides noticeable faster text rendering speed. Note that these gains will be mostly noticeable in specific scenarios such as VisualBrushes, DrawingBrushes, Viewport2DVisual3D , and not everywhere

Improved Z-index Scenarios

  • We significantly improved performance of scenarios that continuously modify Z-Index property of Panel elements (such as in a 2D Carrousel scenario)

Remoting

Although we have not improved this scenario, it is important to highlight some differences related to Remoting
On .Net Framework 3.0 and .Net Framework 3.5:

  • Vista to Vista with DWM on, we Remoted content as Primitives (e.g. the channel protocol went over the network) (This is for the Remote Desktop case only, not Terminal Server)
  • In other cases: we Remoted content as Bitmaps

On .Net Framework 3.5 SP1

  • We now remote as bitmaps in ALL cases.
  • The reason is that WPF 3.5 SP1 now uses a new graphics DLL (wpfgfx.dll) and certain changes could not be made to Vista’s existing graphics DLL (milcore.dll) that is also used by DWM.
  • Although this could be seen a regression at first, depending on the complexity of the application scene (e.g. very rich scenes) this can actually improve performance in certain scenarios . Also, connections with reasonably high bandwidth and scenarios that don’t involve a lot of animation or 3D, for instance, tend to remote just fine via bitmaps.

New “Nearest Neighbor” BitmapScaling Mode

  • We added NearestNeighbor interpolation mode to the BitmapScalingMode enumeration. This should provide further performance benefits over LowQuality mode when using the software rasterizer and more importantly, it provides missing functionality to scenarios such zoom-in while editing a bitmap in a “Paint” program. Without this feature WPF would produce blurry results.

Minor improvement to Tier APIs

  • Two new members added to RenderCapability class to allow applications to fine-tune their use of shader-based Effects:
    • IsPixelShaderVersionSupported(major, minor) : indicates whether the system the specified Pixel Shader version on the GPU.  This is useful for understanding whether effects that you want to run will run in H, as you may potentially want to exclude them if they don't run in hardware.
    • IsShaderEffectSoftwareRenderingSupported: Boolean indicating whether the system supports SSE2 and where the HLSL “JIT” will work.

Smoother animations

  • Almost all of our Animation smoothing improvements already included in .Net 3.5 , however some additional (smaller) improvements are included in Vista Service Pack 1.

Layered Windows improvements

I have blogged about the availability of QFEs for Vista and XP before.
These fixes now included in the recently released Windows XP Service Pack 3 and in Vista Service Pack 1
Note that there is a difference fix on each platform.
On XP: Huge improvements as now render in HW vs. SW before
On Vista: Smaller but still significant improvement to readback from GPU

Controls Improvements

Improved scrolling performance (by introducing Container Recycling support)

  • As user is scrolling through items in a control we re-use the UI elements that go out of view (as oppose to destroy and recreate these elements in .Net 3.0 and 3.5). This turns out to provide significant scrolling improvements.
    We see up to 40% scroll performance improvement in the basic case (e.g. elements contain text). We call this feature Container Recycling.
  • Container Recycling is supported in WPF controls that use VirtualizingStackPanel, namely: ListView, ListBox, TreeView
  • This is an opt in feature, your app need to add the Recycling mode to take advantage of this improvement:
    <ListBox …VirtualizingStackPanel.VirtualizationMode="Recycling" />

Added virtualization support to TreeView control

  • We now added virtualization support to the TreeView control, similar to ListView and ListBox.
  • This ensures that TreeView is not consuming huge amount of memory when it contains large number of elements (e.g. 1,000’s) and it also expends much faster. This enable scenarios that were not possible before (e.g. Windows Explorer) .
  • This is an opt in feature, your app need to use IsVirtualizing in order to take advantage of this improvement:
    <TreeView …VirtualizingStackPanel.IsVirtualizing = “true” />
  • Note that the TreeView also supports the Container Recycling feature mentioned above, so in order to take advantage of this improvement you must do:
    <TreeView …VirtualizingStackPanel.IsVirtualizing=“true”...  VirtualizingStackPanel.VirtualizationMode="Recycling" />

Deferred Scrolling

  • This provides a perceived perf improvement for scrolling. It keeps the content in view as static until scrolling is complete, similar to how Microsoft Outlook scrolls.
  • You could use the ScrollViewer.ScrollChanged event and write your own code to display preview thumbnail during scroll if you like.
  • This is an opt in feature, so your app needs to add IsDeferredScrollingEnabled property in order to take advantage of this feature. E.g.
    <ListBox …ScrollViewer.IsDeferredScrollingEnabled = “true" />

Better fundamentals for DataGrid control
Various enhancements were made to enable developers to write a faster and better DataGrid:

  • Container Recycling
    • Discussed earlier…
  • Column Virtualization Extensions
    • New APIs added to VirtualizingStackPanel that exposes hooks to enable writing your own custom panel with virtualization in the horizontal direction. These could be used by a DataGrid or by other custom panels.
  • Other non-perf DataGrid related features:
    • MultiSelector support to handle multi-selection and bulk editing scenarios
    • IEditableCollectionView - New interface between data controls and data source that enables editing/adding/removing items in a transactional way.
    • StringFormat - shortcut to display data bound number as formatted text
    • Alternating Rows - Enables setting alternating properties on rows of ItemsControl (e.g. alternating background colors in a DataGrid)
    • Conversions for Null Values - Recognize null values in editable controls and convert to appropriate value based on type. It also adds TargetNullValue property which enables app author to designate any value as equivalent to “null”
    • Item-Level Validation - By using Binding Groups this applies validation rules to an entire bound item. For example it can enable validate & commit scenario for a form with few bind-able edit fields. (available in final RTM bits only)
Startup Improvements

Various enhancements were made to improve WPF application startup time
a) Improved Coldstart time

  • By optimizing how we layout the code blocks within CLR and WPF NGEN images we improved the disk IO access patterns we are measuring up to 40% faster coldstart time on average. (we define 'coldstart' for the first WPF app you launch after system re-boot)
  • These gains are depending on the scenario and the application size. Larger apps likely to see better gains than small apps.

b) Improved coldstart for strong-name signed assemblies not GAC’d.
In certain deployment scenarios, an app author may choose to strong-name sign their application assemblies but not to GAC the assemblies because it requires admin privileges.
In this scenario, the entire assembly had to be read off the disk so the CLR can do the hash verification. This had a significant coldstart hit.
In .Net 3.5 SP1 the CLR bypassed this hash verification by default, which means that the app have less disk seeks and disk read and therefore startup time is improved. (As indicated in this blog the majority of coldstart time is spent on disk access.)
The expected startup gains depends on the assemblies size and on what else the app is doing in its startup, but in one scenario we measured ~5% coldstart gains in addition to the gains measured in (a).
If you want to disable this default, an app author can provide a config file (e.g. YourApp.exe.config) and add this:
<configuration>
      <runtime>
             <bypassTrustedAppStrongNames enabled=”0” /> 
    </runtime>
</configuration>
You can find more details in this blog.

c) XBAP coldstart improvements

  • By improving the concurrency of the ClickOnce download sequence we are now seeing up to 10% startup gains for XBAPs scenarios in addition to the gains measured in (a).
  • Up until 3.5 SP1, the XBAP progress UX was rendered using WPF, which means we had to coldstart the CLR and WPF. Starting with .Net 3.5 SP1, we now render the progress UX using HTML which will be shown almost instantly and will improve the perceived startup performance.

d) Splash Screen to improve perceived startup

  • Although coldstart time is improved, it is still not instant. In .Net 3.5 SP1 we are adding new public Splash Screen APIs to allow developers to easily add Splash Screen and make their application startup experience more responsive.
  • Some simple customization is possible with these APIs.
  • An intuitive integration with Visual Studio 2008 SP1 to make this experience even easier is coming in RTM.
  • Note: these APIs will only be available in the RTM bits

Important note: Although we made some impressive improvements to WPF application startup, don’t expect it to be as fast as Win32 application or Winform. WPF simply load more code off the disk. We still expect application developers to properly optimize their app for faster startup and follow the recommendations provided in this blog.

Deployment Improvements
  • .NET Framework 3.5 Client Profile (Client Profile): Smaller and faster redistribution of .Net Framework 3.5 SP1 with a download size of close to 28MB for client applications.
  • Brand-able deployment UX
  • New, smaller deployment and bootstrapper
  • Framework install integrated with Application. Installer can launch app after the framework installed. Supports .msi, .application or .xbap
  • Read more in this blog as well as this

Other Improvements

Memory footprint

  • Modest improvements to working set, especially during startup
  • We fixed few memory leaks mostly related to usage of Image control.
    More details and additional info on how to find and avoid memory leaks in WPF is in my blog.

Improvements to NGEN / JIT

  • The NGEN throughput is improved
  • Modest improvements to JIT time & execution time of the JIT-ed code

Memory Leaks in WPF based applications – Blog Update

We discovered few other potential memory leaks that WPF based application can encounter so I wanted to update my original Finding Memory Leaks in WPF-based applications blog and the sample in that blog with more info on these potential leaks.

Please review the blog updates and use the suggested workarounds to avoid such leaks in your WPF application (or upgrade to the .Net 3.5 Sp1 release when it becomes available).

These potential memory leaks could happen if you use the Image control when:

a) You use BitmapImage as the Image source and do not release the BitmapImage. E.g:

static BitmapImage bi1 = new BitmapImage(new Uri("Bitmap1.bmp",UriKind.RelativeOrAbsolute));
m_Image1 = new Image();
m_Image1.Source = bi1; 
//bi1.Freeze() //if you do not Freeze, your app will leak memory MyStackPanel.Children.Add(m_Image1);

b) You assign multiple BitmapImage as the Image source and do not release all of the BitmapImage you used (similar to (a)). This one introduced in .Net 3.5 ). E.g.:

static BitmapImage bi1 = new BitmapImage(new Uri("Bitmap1.bmp",
UriKind.RelativeOrAbsolute));
static BitmapImage bi2 = new BitmapImage(new Uri("Bitmap2.bmp",
UriKind.RelativeOrAbsolute));
bi2.Freeze();
m_Image1 = new Image();
//bi1.Freeze() //even though you are really using bi2 for Image Source, you also need to Freeze bi1 it to avoid leak m_Image1.Source = bi1; // use un-frozen bitmap, which causes the leak m_Image1.Source = bi2; // use frozen bitmap MyStackPanel.Children.Add(m_Image1);

c) You use BitmapImage that was downloaded from the Web as the Image source. E.g. below will leak:

BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(@"http://www.somesite.com/some_image.png", UriKind.RelativeOrAbsolute);
image.CacheOption = BitmapCacheOption.OnLoad;
image.CreateOptions = BitmapCreateOptions.None;
image.EndInit();                
m_Image1 = new Image();
m_Image1.Source = image;   
MyStackPanel.Children.Add(m_Image1);

See items (5), (6) and (7) in the blog for more detailed documentation, samples and workarounds.

Please note that these are fixed in the upcoming .Net 3.5 Sp1 release, so one potential workaround is to upgrade.

Posted by jgoldb | 1 Comments
More Posts Next page »
 
Page view tracker