信息
您所需的主题如下所示。但此主题未包含在此库中。

Windows Phone 8 的应用性能注意事项

2014/6/18

适用于:Windows Phone 8 和 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

在为 Windows Phone 手机创建应用时,需要重点考虑性能。与台式机或便携式 PC 相比,Windows Phone 手机的中央处理单元 (CPU) 和图形处理单元 (GPU) 有限。为了在 Windows Phone 上优化应用的性能,对 XAML 处理图形和其他对象的方式做出了一些更改。本主题介绍可以改进 Windows Phone 应用性能的一些方法,同时还包括多个代码示例。

本主题包括以下部分。

有多个工具可以帮助优化 Windows Phone 应用的性能。

工具

描述

Windows Phone 的监视分析

帮助您识别问题,如启动时间过慢、对输入的响应时间过慢和高电池消耗量。

Windows Phone 应用程序分析

允许您在代码中度量、评估和确定与性能有关的问题。

Windows Phone 模拟器中的帧速率计数器

使用帧速率计数器可监视应用的性能。

EnableRedrawRegions

启用在开发过程中使用的诊断功能,可以通过显示重新绘制每个帧的区域来优化应用的性能。

此外,对于 Windows Phone 8,通过 商店 分发应用后,应用的部署方式及其在手机上的运行方式有所更改。有关更多信息,请参见在 Windows Phone 中如何测试应用的零售版本

识别图形密集型应用的性能问题一节介绍了有关这些工具的更多信息。

有关在应用中包括图像的注意事项有很多,这些注意事项能提供更好的性能。本节介绍图像特定的注意事项。

在 JPG 和 PNG 图像格式之间进行选择

对于改进应用中的性能,您可以做的最简单的一件事是使用适当的图像格式。Windows Phone 支持两种图像格式:JPG 和 PNG。通常情况下,JPG 解码器比 PNG 解码器要快捷得多,应该用于完全不透明的图像。使用透明度的图像应该存储为 PNG 格式,因为 JPG 格式不支持透明度。请注意,虽然 JPG 非常适合连续色调的图像(包括照片),但是可能会导致在包含不同颜色和渐变色的图像中出现边缘振荡和块效应。

图像创建

一个值得注意的 Windows Phone OS 7.1 性能优化是选择将图像解码过程移动到后台线程而不是阻止 UI 线程。这可以通过将 CreateOptions 属性设置为 BackgroundCreation 来实现。例如:

<Image Height="100" Width="100" Margin="12,0,9,0">
  <Image.Source>
    <BitmapImage UriSource="{Binding ImgURL}" CreateOptions="BackgroundCreation"/>
  </Image.Source>
</Image>

在图像和 XAML 之间进行选择

在 Expression Design 中,可以创建复杂的视觉效果。可以将这些视觉效果导出为 XAML 或图像文件。当视觉效果为静态时,应该考虑将其存储为图像而不是 XAML。与解码和呈现图像相比,XAML 可能需要进行更多的处理。将 XAML 用于视觉效果的过程需要分析 XAML、在可视化树中创建对象并呈现对象。例如,如果要创建一个跳棋游戏应用,则可以使用 Expression Design 为游戏中的每个棋子创建一个复杂设计。但是,由于棋子是静态的,因此对于应用的性能来说,更好的做法是将棋子导出为图像而不是 XAML。

限制图像大小

由于 Windows Phone 的屏幕分辨率受限制,因此优化性能的另一种方法是将图像大小限制为 2000 × 2000 像素,这是 Windows Phone 环境中图像的大小限制。较大的图像将以较低的分辨率进行采样。此外,如果您使用的图像分辨率高于 2000 × 2000 像素,则它们的显示将明显更慢一些。

如果必须使用分辨率高于 2000 × 2000 像素的图像,则应该只显示满足 2000 限制的文件部分。若要做到这一点,您可以将图像加载至 WriteableBitmap 中,以及使用 LoadJpeg(WriteableBitmap, Stream) 扩展方法。以下代码显示加载大图像时建议使用的方法。

下载此示例

<StackPanel>
    <Image Height="3000" Width="3000" Name="image1" Stretch="Fill" />
    <Button Content="Load" Height="70" Width="152" Click="btnLoad_Click" />
</StackPanel>

private void btnLoad_Click(object sender, RoutedEventArgs e)
{
    StreamResourceInfo sri = null;
    Uri uri = new Uri("LoadJpegSample;component/Test3k3k.JPG", UriKind.Relative);
    sri = Application.GetResourceStream(uri);

    WriteableBitmap wb = new WriteableBitmap((int)this.image1.Width, (int)this.image1.Height);

    wb.LoadJpeg(wb, sri.Stream);
    this.image1.Source = wb;
}

WinPhonePerf_LoadingLargeImages

Windows Phone 中的 MediaElement 依赖于本机媒体处理和 Windows Phone 操作系统中包含的硬件解码器。因此,开发人员应注意媒体处理和播放方式的两点差异:

  • Windows Phone 上的播放速率和分辨率受限制。

  • 内存中的流未针对播放进行优化。

编码媒体以获得最佳播放速率和分辨率

您应该编码媒体以满足 wphone 的最佳播放速率和分辨率要求。有关受支持的媒体编解码器和最佳播放速率和分辨率的完整列表,请参阅支持的 Windows Phone 媒体编解码器

将媒体的生成操作设置为内容

对 Windows Phone 上的媒体处理进行优化以使用文件和网络流,而不是使用内存中的流。这意味着应用中包括的任何媒体文件(例如声音效果)应该将其“生成操作”设置为“内容”而不是“资源”。当媒体文件作为内容编译时,它会作为松散文件与应用文件 (.XAP) 一起存储,而不是存储在应用程序文件中。当媒体文件作为资源编译时,通常通过检索文件流来访问,这可能会降低性能。此外,当播放编译为内容的媒体文件时,会直接进行播放。当媒体文件作为资源编译时,播放之前需要将内容复制到 Windows Phone 上的文件,这会降低性能。下图显示如何在 Visual Studio 中设置文件的“生成操作”。

WinPhonePerf_BuildActionContent

如果必须播放内存中的流,可以提供 MediaStreamSource 的实现。如果无法提供 MediaElement 的实现,另一个解决方案是将流保存到隔离存储中的文件并从该位置进行访问。

可以通过两种方式隐藏屏幕上的对象。您可以使用 Visibility 属性或 Opacity 属性。通过理解每种技术的性能影响,可以在应用中优化转换。

Visibility 属性

当您将元素的 Visibility 属性设置为 Collapsed 时,XAML 不会在虚拟内存中保存元素的任何可视数据,也不会执行任何与元素相关的处理。但是,当您通过将 Visibility 设置为 Visible,在屏幕上显示该元素时,必须再次绘制可视化树中的内容。元素会完全重新绘制。

不透明度属性和位图缓存

若要提升应用的性能,您可以在使用位图缓存的时候,操作元素的 Opacity 属性。若要使用位图缓存,则将 CacheMode 属性设置为 BitmapCache。在首次呈现处理过程之后,位图缓存允许将可视元素存储为位图。在缓存该元素之后,应用会跳过缓存可视元素的呈现处理过程,而显示存储的位图。您应该避免在不启用缓存的情况下操作 Opacity,因为这可能会降低应用的性能。

当您将缓存元素的 Opacity 设置为 0 时,元素的位图表示将保存在内存中。只要构图线程不支持的属性不发生更改,此元素就会一直保存在内存中。在将 Opacity 设置回非零值时,将应用标准填充速率。

在可见性和不透明度之间进行选择

通常,您将通过结合位图缓存使用 Opacity 属性来提高性能。但是,有时使用 Visibility 属性将会取得更好的性能,例如在您的应用包含多种丰富的视觉效果时。应逐项评估每种技术的性能。您可以通过编写在 VisibilityOpacity 属性之间进行切换的代码来执行此操作。

隐藏对象示例

本示例允许您通过设置 OpacityVisibility 属性进行实验,来确定哪个属性在应用中的执行效果更好。

下载此示例

运行此示例时,您将看到 1 个应用了动画的蓝色正方形、1 个应用了动画的红色正方形和 150 个矩形。您还将看到以下按键:

  • Opac x% - 将矩形的 Opacity 设置为指定的百分比。

  • Cache - 切换是否缓存矩形。默认为 true。

  • Collapse/Visible - 切换矩形的 Visibility 属性。默认值为 Visible

若要测试此示例,请尝试以下操作:

  • 切换 Visibility 并更改矩形的 Opacity。注意,当 Opacity 相对于 Visibility 发生更改时,矩形的显示速度更快。还请注意,在 Opacity 是 0 以外的值时,动画显示较慢。这是因为 150 个矩形影响了填充速率。

  • 操作禁用了缓存的矩形。您将注意到正方形的动画非常流畅,因为这些矩形并未影响填充速率。您还应该注意到设置 Opacity 或切换 Visibility 时,显示矩形所花费的时间没有区别。这是因为如果不进行缓存,在所有情况下都必须重新绘制矩形。

WinPhonePerf_HidingObjects

Windows Phone 中的用户输入包括操作事件、鼠标事件和触控事件。

使用操作事件

建议使用操作事件处理用户输入。除非有特定需要,否则出于性能和硬件兼容原因,应该避免在 Windows Phone 的应用中使用鼠标事件。而是应该使用操作事件。您还可以对从 UIElement(例如基控件)派生的任何元素使用 TapDoubleTapHold 事件。

Touch 类提供 FrameReported 事件,该事件用于获取单个触控接触点。尽管 Windows Phone 支持该事件,但在尝试处理手势(例如捏合和拉伸)时,不建议使用此事件。如果您不需要单个触控接触点,则应该使用操作事件。

有关如何使用操作事件的更多信息,请参阅如何处理 Windows Phone 的操作事件

当您执行非常耗时的操作时,应该使用进度指示器向用户指示应用仍然在运行。若要指示进度,可以使用下列控件中的一种。

  • 可以使用 ProgressIndicator 在系统托盘中显示进度指示器。内置应用往往使用 ProgressIndicator

  • 可以在 Visual Studio 工具箱中使用进度栏控件。有关如何使用该控件的更多信息,请参见 ProgressBar 类。

使用 Windows Phone SDK 7.1 进行开发时,请使用 PerformanceProgressBar 而非 ProgressBar

如果您使用的是 Windows Phone SDK 7.1,那么使用 Visual Studio 工具箱中的进度栏报告不确定的进度可能会降低应用的性能。在 Windows Phone SDK 8.0 中,ProgressBar 类已经更新,使用工具箱中的进度栏不会降低您在 Windows Phone 8 上的应用的性能。

为了解决 Windows Phone SDK 7.1 中的 ProgressBar 性能问题,Microsoft 创建了一个不支持的替代方法,名为 PerformanceProgressBarPerformanceProgressBar 将动画从 UI 线程移动到排字线程。有关更多信息,请参见添加自定义的不确定进度栏

在 Windows Phone 8 中,您可以选择使用 LongListSelector 来显示项目的列表,并且相较于 ListBox 控件,它是首选控件。

为了延长电池使用时间,在预先配置的超时间隔之后,操作系统将关闭手机的收音机。如果应用将对少量数据发出大量请求,则我们建议以并行方式(而不是串行方式)执行这些请求。这有助于确保手机的收音机堆栈不会进入睡眠状态,从而避免在对每个请求打开或关闭收音机时产生滞后。

当应用加载或启动时,您可以做很多事情来提高性能。本节包括以下事项。

使用初始屏幕

您的应用设计可能要预加载某些资源并且确保这些资源在应用可供交互前可用,即使这意味着在下载完成前不显示该应用。初始屏幕是一个初始的内容区域,可在其他内容仍在加载时向用户显示。

警告说明警告:

通常,Windows Phone 8 应用能够非常迅速地启动且无需初始屏幕。

Windows Phone SDK 7.1 项目模版包含默认初始屏幕图像,名为 SplashScreenImage.jpg。应用启动时,它会自动出现。您可以修改在 Windows Phone SDK 7.1 项目模板中提供的默认初始屏幕图像,或者也可以向 Windows Phone SDK 8.0 项目添加一个初始屏幕。创建您自己的图像以显示品牌和产品信息(例如,应用的免责声明)。

若要自定义初始屏幕,您可以使用自己的图像替换默认图像。您可以用您所选的任何图像替换默认图像,但是它必须大小合适,并且要把它命名为 SplashScreenImage.jpg。您可以显示品牌和产品信息,例如应用的免责声明或其他信息。对于 Windows Phone OS 7.1 应用,初始屏幕图像必须为 480 × 800 像素。对于 Windows Phone 8 应用,初始屏幕图像必须为 768 × 1280 像素。图像缩放为适用于运行该应用的手机的合适分辨率。您也必须将图像的生成操作属性设置为内容

有关添加或修改初始屏幕的更多信息,请参见如何为 Windows Phone 创建初始屏幕

另一个选项是显示应用第一个页面的屏幕捕获,给人应用正在快速启动的印象。如果您希望将应用的屏幕捕获用于初始屏幕,请在进行屏幕捕获时注意以下事项:

  • 隐藏应用运行时更改的任何数据。

  • 确保模拟器设置为 100% 的比例。

  • 剪切图像以削除模拟器镶边。

  • 确保您的图像大小合适,并且另存为 SplashScreenImage.jpg。

对于需要长时间加载的应用,建议您在应用准备运行时,创建初始屏幕动画来指示进度。

如果您要在不延迟加载时间的情况下将重要信息显示在初始屏幕中,请确保原始屏幕为初始屏幕的正确副本。例如,您可以重写页面的 OnNavigatedTo(NavigationEventArgs) 方法,然后创建一个包含同一初始屏幕图像的弹出窗口,并显示希望初始屏幕显示的时间长度。

最大程度减小应用程序集的大小

可以改进应用启动的另一种方法是最大程度地减小应用程序集的大小。当您将应用提交到 Windows Phone 应用商店 时,将会出于验证目的对其进行签名,并且在每次应用启动时会检查该签名。检查程序集签名所花费的时间量会随着应用程序集大小的增加而增加。由于将缓存签名,签名检查对应用后续加载的影响有限,但仍将影响应用的首次加载。以下是减小程序集大小的一些提示:

  • 如果可能,不要将“生成操作”设置为“资源”,从而在程序集中包括资源,如图像、媒体和和 XML 文件。而是将这些文件的“生成操作”设置为“内容”。

  • 使用前导斜杠设置图像的源 URI 路径,如“/folder/myImage.jpg”。

  • 除非需要使用透明度,否则使用 JPG 图像代替 PNG 图像。

  • 如果您的应用经过本地化,则不要将本地化的资源包括在主应用程序集中,而是为每种语言创建附属程序集。有关更多信息,请参阅如何生成 Windows Phone 的本地化应用

说明注意:

如果要创建一个可重用的控件或组件,应通过将资源的“生成操作”设置为“资源”以在应用中包括这些资源。在此情况下,应慎用图像和资源。

将应用分解为较小的程序集

为了将启动时间降到最低,可以将应用分解为一些仅在需要时加载的小型程序集。可以通过向应用添加一个保存要按需加载的页面的新 Windows Phone 类库项目,执行上述操作。然后根据需要向该项目添加 Windows Phone 页面,并从主应用项目中引用类库项目。您可以使用超链接按键或添加事件以使用户能够在页面之间进行导航。下面的代码示例显示如何导航到名为 ExternalPage.xaml 的页面,该页面位于名为 PageInExternalAssembly 的程序集中。

下载此示例

private void button1_Click(object sender, RoutedEventArgs e)
{
     // Use the name of the separate assembly when generating the Uri for the page
     NavigationService.Navigate(new Uri("/PageInExternalAssembly;component/ExternalPage.xaml", 
           UriKind.Relative));
}

最大程度地减少构造函数和 Loaded 事件中的代码

该页面的 Loaded 事件处理程序中的所有构造函数和代码在应用的第一帧显示之前运行。页面和控件构造函数会分析 XAML 并实例化在 XAML 中声明的对象,这可能非常耗时。因此,您应该在这些方法中限制使用其他长时间运行的操作。如果您需要加载文件或执行其他繁重的处理,则应该在以后的事件中执行此操作或安排在后台线程上执行。您可以执行此操作的一种方法是重写 OnNavigatedTo(NavigationEventArgs) 并在此方法中启动长时间运行的进程。当页面成为活动页面时,将调用 OnNavigatedTo。下面的示例演示如何执行此操作。

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    // Do lengthy page initialization in a new 
    // thread so the UI can continue to update.
    System.Threading.Thread startupThread = 
        new System.Threading.Thread(new System.Threading.ThreadStart(initializePage));
    startupThread.Start();
}

void initializePage()
{
    // Do lengthy page initialization here...
}

监视独立存储的使用

ApplicationSettings 对象是一个单一实例,它在首次使用对象时(通常是在启动应用时)从存储中进行分配和反序列化。您可以在应用中创建帮助器属性以访问 ApplicationSettings,并通过在帮助器属性中放置一个定时器来测量反序列化应用设置所用的时间。如果完成数据反序列化操作所用时间超过 100 毫秒,则应该考虑将此操作移动到后台线程上的调用。

如果您使用独立存储中的数据填充页面,则应该分配 ObservableCollection<T> 对象以存储数据,并立即将集合绑定到 UI 中的元素。然后您应该使用独立存储中的数据填充 ObservableCollection 对象。如果需要,您可以通过使用 BeginInvoke(Action) 方法将数据填充分散到多个调用中。

避免阻止 UI 线程

可能阻止 UI 线程从而延迟应用启动的方式有许多。以下服务和 API 可能会阻止 UI 线程:定位服务、推送通知、网络信息和收音机。

定位服务

在 Windows Phone 启动后,PositionChanged 事件要过几秒才能在 GeoCoordinateWatcher 上发生。根据 DesiredAccuracy 的设置,可能要经过 3 到 13 秒才会首次发生 PositionChanged 事件。这是由于定位服务启动服务、查找附属程序集和执行其他操作要花费时间。如果 Windows Phone 已在运行,则此操作不会花费太长时间,通常 PositionChanged 事件会在 500 毫秒内发生。如果您的调用依赖于位置事件的发生,则可能会阻止 UI 线程并减慢应用的启动。有关如何使用定位服务的更多信息,请参阅 Windows Phone 8 定位

推送通知

使用 Microsoft 推送通知服务,可以通过 Web 服务在应用中接收更新。推送通知 API 是异步的,因为对推送通知服务的某些调用可能要花费很长时间才能返回。应始终避免出现 UI 线程等待推送通知服务调用返回的情况。例如,您可以在 UI 线程上创建并打开一个到推送通知服务的通道,但不会造成 UI 线程等待此事件发生的情况。有关更多信息,请参阅 Windows Phone 的推送通知

网络信息

当 Windows Phone 启动时,对 GetIsNetworkAvailable() 的首次调用,可能最多需要花费 20 秒的时间才能返回。这是因为 Windows Phone 最初将枚举所有可用的网络连接。

收音机

当 Windows Phone 启动时,对 FMRadio 类的调用可能最多需要 3 秒的时间才能返回。在初始化收音机之后,这些调用返回所花费的时间应该减少到 100 毫秒。不应该在 UI 线程上设置或调整收音机,而是应该使用后台线程执行此操作。 有关更多信息,请参阅本主题后面的后台线程和异步编程一节。

Windows Phone 的图形线程结构针对手机进行了优化。除了 UI 线程之外,Windows Phone 还支持构图线程。若要了解如何优化 Windows Phone 的性能,应了解 Windows Phone 中的两个主线程以及如何使用后台线程,这一点非常重要。

UI 线程

UI 线程是 Windows Phone 中的主线程。以下是 UI 线程处理的任务列表。

  • 从 XAML 中分析并创建对象。

  • 在第一次绘制视觉效果时,将绘制所有视觉效果。

  • 处理每帧回调并执行其他用户代码。

维护轻量级 UI 线程对编写响应应用至关重要。

构图线程

构图线程处理 UI 线程通常会处理的一些工作,因此提高了 Windows Phone 应用的性能。构图线程合并图形纹理并将其传递到 GPU 以供绘制。此外,在 Windows Phone 上,手机上的 GPU 将在称为自动缓存的进程中,自动缓存并处理运行在构图线程上的演示图板驱动的动画。

构图线程处理与 RenderTransformProjection 属性关联的简单动画。以下列表显示构图线程通常处理的动画。

说明注意:

若要使用构图线程,缩放变换必须小于原始大小的 50%。

此外,OpacityClip 属性设置也由构图线程处理。但是,如果使用 Opacity 蒙板或非矩形剪辑,则这些操作将被传递到 UI 线程。

动画和线程

如前所述,演示图板驱动的动画由构图线程进行处理。这最为理想,因为构图线程会将这些动画传递到 GPU 进行处理。此外,如果 CPU 超负荷,则构图线程可能比 UI 线程运行的更频繁。但是,有时演示图板动画不满足您应用的要求。在这种情况下,您可以选择在代码中驱动动画。这些动画按帧进行处理。在许多情况下,这种做法尚佳,但应注意在每帧回调上运行动画的影响。

每帧回调严格在 UI 线程上进行处理。动画的更新速度与 UI 线程处理动画的速度相当,并且根据应用中发生的其他操作,动画显示的流畅性可能低于在构图线程上运行。此外,当您在代码中更新动画时,元素不会像在演示图板中更新一样,自动进行缓存。如果您手动将位图缓存放置在这些元素上,则转换和混合会被传递到 GPU,但是动画仍然会在每帧回调上进行更新并由 UI 线程进行处理。在这些情况下,动画的更新速度将与 UI 线程的帧速率相当。

后台线程和异步编程

为了避免阻止 UI 线程的复杂进程,可以卸载对次要线程(称为后台线程)的处理,并异步执行此处理。例如,Web 服务 API 便被设计为异步使用,因此它们不会阻止 UI 线程。如果您使用后台线程,则必须提供一种机制,将数据从后台线程移动回 UI 线程。您可以通过共享变量和前后移动数据的事件执行此操作,也可以通过使用 BeginInvoke(Action) 方法向 UI 线程发送通知来执行此操作。或者,可以使用 BackgroundWorker 类及其基于事件的机制进行异步处理。有关更多信息,请参见如何使用 Windows Phone 的后台辅助线程

监视您应用的性能并识别性能问题的方法有多种。一种方法是监视您应用的内存使用情况。您还可以启用重绘区域和缓存可视化的着色,以便可以直观地监视这些效果在应用中的使用情况。您还可以打开可供 Windows Phone 模拟器使用的帧速率计数器。使用帧速率计数器您可以监视应用性能的许多不同方面。以下各节说明如何使用这些功能。

监视内存使用情况

您应该监视应用的内存使用情况。要完成此操作,可以调用 DeviceStatus API 的几个属性。有关更多信息,请参阅 Windows Phone 的设备状态。您也可以使用 Windows Phone 商店测试工具包评估应用的总内存使用量。有关更多信息,请参见 Windows Phone 商店测试工具包

启用重绘区域

通过启用 Windows Phone 模拟器中的重绘区域,您可以直观地查看正在绘制的应用的区域。在您页面的构造中,将 EnableRedrawRegions 属性设置为 true。您可以通过当前应用设置访问此属性,如以下代码中所示。

Application.Current.Host.Settings.EnableRedrawRegions = true;

现在,当您运行应用并且某个区域已完全绘制时,该区域会使用某种颜色进行着色。经过着色的区域表示使用 CPU 而非 GPU 执行绘制操作。当使用 CPU 绘制时,称为软件绘制。软件绘制是普通绘制,因为所有内容必须在第一次显示时由软件进行绘制,但是您应该查找过量软件绘制。如果您的应用包含更改每帧的闪烁颜色,则应考虑对这些元素使用位图缓存。

启用缓存可视化

通过启用缓存可视化,可以直观地查看哪些图形纹理正在使用并传递到了构图线程,哪些又传递到了 GPU。为此,请在您页面的构造函数中,将 EnableCacheVisualization 属性设置为 true。您可以通过当前应用设置访问此属性,如以下代码中所示。

Application.Current.Host.Settings.EnableCacheVisualization = true;

当您启用缓存可视化时,应用中的每个纹理都会应用一个蓝色色调和透明度。这样您就可以查看应用中的各种纹理以及它们重叠的位置。蓝色的最暗阴影表示多个纹理在彼此顶部重叠的区域。您可以查看应用中的隐藏对象,这些对象可能会导致高填充速率。Windows Phone 缓存可视化与其他平台上的缓存可视化略有不同。在其他平台上,着色区域表示未由开发人员显式缓存的纹理。但是,在 Windows Phone 上,每个着色区域都表示传递到 GPU 以供构图的纹理。这对监视器来说非常重要,因为随着应用在视觉上变得更复杂,它可能超出 GPU 的功能范围。

当您启用缓存可视化时,GPU 必须执行额外的工作并且可能会对帧速率产生负面影响,因此使用此标志时不应该依赖于帧速率计数器。

启用帧速率计数器

Windows Phone 模拟器提供了在开发应用时监视其性能的帧速率计数器。当附加调试器时,默认情况下会在 App 构造函数中启用帧速率计数器,如以下代码中所示:

// Show graphics profiling information while debugging.
if (System.Diagnostics.Debugger.IsAttached)
{
    // Display the current frame rate counters.
    Application.Current.Host.Settings.EnableFrameRateCounter = true; 
说明注意:

您可能需要将 SystemTray.IsVisible 属性设置为 false 才能看到帧速率计数器。

下图显示了帧速率计数器。

Frame Rate Counters with Labels

下表描述了每个帧速率计数器。

计数器

描述

构图线程帧速率

此值指屏幕更新的速率。它还表示更新演示图板驱动的受支持动画的频率。此值应尽可能接近 60。当此值小于 30 时,应用的性能开始降级。当显示的值小于 30 时,此计数器中的文本为红色。

UI 线程帧速率

此值指 UI 线程运行的速率。UI 线程驱动输入、每帧回调以及构图线程不处理的任何其他绘制。该值越大,应用的响应性就越好。为了向用户输入提供可接受的响应时间,通常该值应该大于 20。当显示的值小于 15 时,此计数器中的文本为红色。

纹理内存使用量

此值表示在应用中正在使用的纹理的视频内存和系统内存副本。对于应用来说,这不是一个通用的内存计数器,仅表示图面使用的内存。

图面计数器

该值提供传递至 GPU 进行处理的显式图面的原始计数。此数字的最大影响因素是自动或开发人员缓存的元素。

中间图面计数器

此值表示由缓存图面生成的隐式图面的隐式图面。这些图面在 UI 元素中间创建,以便应用可以准确地保持 UI 中元素的 Z 顺序。

填充速率计数器

此值表示以屏幕为单位每帧绘制的像素数量值 1 表示 480 x 800 像素。建议值是 2.5 左右。当显示的值大于 3 时,此计数器中的文本变为红色。

监视填充速率

填充速率是图形纹理中为每帧传递到 GPU 进行构图的像素数。填充速率实质上是 GPU 工作量的度量。因此,您应该注意应用的填充速率,因为它很容易超出 GPU 的功能范围,从而导致帧速率下降。当应用的填充速率超出 2 个屏幕 (800x480) 像素时,帧速率将开始下降。通常填充速率下降对用户来说是并不明显的,除非填充速率达到约 3.5 屏幕像素值。通过查看帧速率计数器中的最后一个数字,您可以确定应用的填充速率。此外,请记住 UI 线程上的帧速率永远也不要超过构图线程上的帧速率,这一点非常重要,因此如果您的填充速率过高,将影响应用的总体性能。

填充速率影响

需要纹理的每个图形对象都会影响应用的填充速率。纹理中的像素越多,填充速率就越高。通常,填充速率包含两个主要的影响因素。第一个影响因素是基本图面,该图面是环绕未缓存的所有内容的矩形。第二个影响因素是缓存的所有内容,其中包括在构图线程上自动缓存的纹理和开发人员通过在元素上设置 BitmapCache 来缓存的元素。除了在构图线程上缓存的纹理之外,下面还有自动缓存的纹理。

建议的帧和填充速率

下表列出了优化应用的性能时,您应该查找的计数器的建议阈值和上限阈值。在实际的 Windows Phone 手机上测试这些计数器非常重要,因为模拟器的性能会有所不同。如果线程上没有正在处理的动画,请注意计数器可能会停止更新。如果您希望一直看到计数器值,则可以在开发和测试期间向应用添加一个非常简单、重复的动画。在发布应用之前,您可以先删除动画。

计数器

红色值阈值*

建议值

上限阈值

构图线程帧速率

30 帧/秒

45 帧/秒

60 帧/秒

UI 线程帧速率

15 帧/秒

30 帧/秒

60 帧/秒

屏幕填充速率

>3

<= 2.5

3.0

*当计数器到达某个阈值时,该值将变为红色。红色值表明存在潜在性能问题。

填充速率测试示例

通过该示例您可以添加和删除动画矩形以查看对填充速率的影响。每个矩形的大小是屏幕的 1/8,由于应用了动画的原因,每个矩形表示一个纹理。

下载此示例

当您运行此示例时,将看到以下三个按键:

  • Add - 添加矩形。

  • Dlt - 删除矩形。

  • Hide - 隐藏“Hide”和“Add”按键,更改要显示的“Dlt”按键。

您还将在右上角看到两个数字。第一个数字表示在单个矩形中屏幕的像素值,第二个数字表示屏幕的总像素值(填充速率)。

若要测试此示例,请尝试以下操作:

  • 添加矩形直到填充速率超过 2,并观察帧速率下降的情况。

  • 添加矩形直到帧速率位于 45 和 60 之间。点按“Hide”按键,您应该会看到帧速率增加和填充速率下降。这是因为保存按键的图面已收缩。当底部的两个按键消失时,图面仅会向下拉伸约屏幕的 10%(相对于按键可见时的 90% 而言)。点按“Show”按键会使帧速率下降,因为图面又再次扩展。

WinPhonePerf_FillRateTest

透视填充速率示例

通过该示例您可以查看平面投影或透视转换在应用性能上的效果。设计器生成的 XAML 通常包含许多透视转换,这些转换可以创造很好的视觉效果,但会影响应用的性能。本示例说明透视和动画的缓存行为。不带动画的透视转换会自动缓存,因此添加动画不会进一步影响性能。但是,向不带透视转换的矩形添加动画确实会对性能产生影响。

下载此示例

当您运行此示例时,将看到四个按键:

  • Add - 添加一个随机矩形。

  • Dlt - 删除最近的矩形。

  • Persp - 切换矩形是否应用了透视转换。

  • Animate - 切换是否对矩形进行动画处理

若要测试此示例,请尝试以下操作:

  • 添加几个矩形直到中间正方形上的动画开始不流畅,然后切换透视按键。您应该看到不流畅的情况消失,因为矩形不再进行缓存。矩形与页面上的按键和文本共享一个图面。在应用透视时,它们会被自动放置在每个矩形上,这会添加一个影响填充速率的图面。

  • 添加几个矩形直到中间正方形上的动画开始变得不流畅。点按“Animate”按键,注意不流畅的情况并没有加重。由于已经自动缓存不带动画的透视,因此在缓存上放置动画不会导致创建任何其他纹理。将此操作与在不带透视的矩形上切换动画的行为进行比较。在不应用透视并且正方形上没有动画的情况下,可以添加任何所需数量的矩形,而且正方形动画不会受到影响。由于这些矩形都没有被缓存,因此它们仍然全部都与文本和按键共享相同的图面。但是,在将动画应用到这些矩形,会在这些矩形上放置一个自动位图缓存,并且将立即影响矩形中每个纹理区域的填充速率。

WinPhonePerf_PerspectiveFillRate

每帧回调示例

通过该示例您可以查看使用每帧回调进行动画处理与演示图板驱动的动画的效果。

下载此示例

当您运行此示例时,将看到一个使用演示图板进行动画处理的小蓝色正方形(因此在构图线程上运行)和以下五个按键:

  • Add - 添加一个矩形,该矩形大小为屏幕的 1/8,并且使用每帧回调进行动画处理。

  • Dlt - 删除最近的矩形。

  • Redraw - 切换 EnableRedrawRegions 调试标志。

  • Cache - 切换矩形是否应用了手动位图缓存。默认为 true。

  • Hide/Show - 切换屏幕底部按键的可见性。

若要测试此示例,请尝试以下操作:

  • 请添加几个矩形,直到蓝色正方形和矩形明显不流畅。这是因为实施了手动缓存。由于手动缓存,因此正方形在排字线程上进行动画处理,而矩形在 UI 线程上进行动画处理。两个线程都由为每帧绘制矩形的填充速率限定。

  • 切换“Cache”按键,该操作会为矩形关闭手动缓存。您应该看到正方形开始非常流畅地进行动画处理,但是矩形将更加不流畅。这是因为在不应用缓存的情况下,UI 线程现在正在为每帧绘制矩形。同时,构图线程不再处理矩形纹理,因此正方形的动画效果非常流畅。如果不缓存矩形,则纹理不会保存在内存中。每次更新矩形位置时,都会从头开始重新绘制像素。这个开销大的操作在 CPU 和 UI 线程上进行。同时,尽管矩形消耗 CPU,轻量构图线程仍能够以每秒 60 帧的速度更新其正方形。

  • 继续实验 redraw 和 cache 按键。注意启用重绘区域后,如果缓存矩形,则矩形不会闪烁。闪烁表示正在从头开始逐帧重新绘制对象,这是您希望避免的。如果矩形未缓存,则将看到应用于矩形每一帧的闪烁的新色调。 请注意,在这种情况下,正方形不再闪烁,因为它正由演示图板动画驱动并且会自动进行缓存。

WinPhonePerf_PerFrameCallback

使用性能分析工具

Windows Phone Performance Analysis 工具是一种分析工具,它作为 Windows Phone SDK 的一部分进行安装。您可以使用该 Performance Analysis 工具识别、评估和改进图形密集型应用的执行和内存性能。

有关更多信息,请参阅 Windows Phone 应用程序分析

显示: