wpf 在渲染时间和性能方面,面板以什么顺序最有效?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9946811/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In what order are Panels the most efficient in terms of render time and performance?
提问by Rachel
There are many times when more than one panel would suitable for the layout I want, however I know there is a difference in render times for different panel types.
很多时候不止一个面板适合我想要的布局,但是我知道不同面板类型的渲染时间存在差异。
For example, MSDNstates that
例如,MSDN指出
A relatively simple
Panel
, such asCanvas
, can have significantly better performance than a more complexPanel
, such asGrid
.
一个相对简单的
Panel
,比如Canvas
,可以比一个更复杂的Panel
,比如Grid
.
So in terms of render time and performance, in what order are WPF panels the most efficient?
那么在渲染时间和性能方面,WPF 面板在什么顺序下效率最高?
WPF Panels:
WPF面板:
Canvas
DockPanel
Grid
UniformGrid
StackPanel
WrapPanel
VirtualizingPanel
/VirtualizingStackPanel
Canvas
DockPanel
Grid
UniformGrid
StackPanel
WrapPanel
VirtualizingPanel
/VirtualizingStackPanel
I'm fairly sure I saw a list of this somewhere online, but I can't find it now.
我很确定我在网上某处看到了这个列表,但我现在找不到了。
The ideal answer I am looking for would provide me a list of panels in the order that they would render fastest. I understand the number of children is a big factor in how efficient the panels are, so for the sake of this question, assume each panel only has a Label
/TextBox
pair.
我正在寻找的理想答案会为我提供一个面板列表,按照它们渲染速度最快的顺序排列。我知道孩子的数量是影响面板效率的一个重要因素,所以为了这个问题,假设每个面板只有一个Label
/TextBox
对。
In addition, I would like a list of exceptions, such as specific panels which perform better than others based on certain conditions.
此外,我想要一个例外列表,例如基于某些条件比其他面板表现更好的特定面板。
Update
更新
To summarize based on the accepted answerbelow, the panel performance is based on the number and layout of child items, however in general the list from fastest to slowest is:
根据下面接受的答案进行总结,面板性能基于子项的数量和布局,但通常从最快到最慢的列表是:
Canvas
StackPanel
WrapPanel
DockPanel
Grid
Canvas
StackPanel
WrapPanel
DockPanel
Grid
In addition, a VirtualizingPanel
/ VirtualizingStackPanel
should always be used if there are a lot of items that don't always fit on the screen.
此外,如果有很多项目并不总是适合屏幕,则应始终使用VirtualizingPanel
/ VirtualizingStackPanel
。
I'd highly recommend you read the accepted answerbelow for more details before just picking an item from this list.
我强烈建议您在从此列表中选择一个项目之前阅读下面接受的答案以了解更多详细信息。
回答by N_A
I think it is more concise and understandable to describe the performance characteristics of each panel than it is to try to give an absolute relative performance comparison.
我认为描述每个面板的性能特征比尝试给出绝对的相对性能比较更简洁易懂。
WPF makes two passes when rendering content: Measure and Arrange. Each panel has different performance characteristics for each of these two passes.
WPF 在渲染内容时进行两次传递:测量和排列。对于这两个遍中的每一个,每个面板具有不同的性能特征。
The performance of the measure pass is most affected by the ability of a panel to accommodate stretching using alignments (or Auto in the case of the Grid
) and then the number of children which are stretched or auto-sized. The performance of the Arrange pass is affected by the complexity of the interaction between layout location of different children and then of course the number of children.
测量通道的性能受面板使用对齐(或在 的情况下为自动)适应拉伸的能力的影响最大Grid
,然后是拉伸或自动调整大小的子项的数量。排列通道的性能受不同子级的布局位置之间交互的复杂性影响,当然还有子级的数量。
At times the given panels don't easily lend themselves to the needed layout. I created a control that needed an arbitrary number of items to each be positioned at a certain percentage of the available space. None of the default controls do this. Attempting to make them do this (via binding to the actual size of the parent) results in horrible performance. I created a layout panel based on the Canvas which achieved my desired result with minimal work (I copied the source for the canvas and modified around 20 lines of it).
有时,给定的面板不容易适应所需的布局。我创建了一个控件,需要将任意数量的项目放置在可用空间的特定百分比处。没有任何默认控件会执行此操作。试图让他们这样做(通过绑定到父级的实际大小)会导致糟糕的性能。我创建了一个基于 Canvas 的布局面板,它以最少的工作实现了我想要的结果(我复制了画布的源代码并修改了大约 20 行)。
Available Panels:
可用面板:
Canvas
Defines an area within which you can explicitly position child elements by coordinates relative to the Canvas area.
The Canvas has the best performance of all the panels for the arrange pass since each item is statically assigned a location. The measure pass also has excellent performance since there is no concept of stretching in this panel; each child simply uses its native size.
DockPanel
Defines an area within which you can arrange child elements either horizontally or vertically, relative to each other.
The Dockpanel has a very simple layout scheme where items are added one by one relative to the previous item added. By default either the height or width is determined by the item's native size (based on Top/Bottom vs Left/Right respectively) and the other direction is determined by the
Dock
property if the width or height is undefined. Medium to fast measure pass and medium to fast arrangement pass.Grid
Defines a flexible grid area that consists of columns and rows.
This can be the most performance intensive panel if proportional sizing or auto sizing is used. Calculating child item size can be a complex combination of the native size of the item and the layout specified by the grid. Layout is also the most complicated of all the panels. Slow to medium performance for the measure pass and slow to medium performance for the arrangement pass.
StackPanel
Arranges child elements into a single line that can be oriented horizontally or vertically.
The StackPanel measures its children using either native or relative sizing in the opposite direction from its orientation and native sizing in the direction of its orientation (alignment does nothing in this direction). This makes it a mid-level performer in this area. The Arrangement pass is simply, just laying out the items in order. Probably the second-best performance for this pass. Medium performance for the measure pass and fast performance for the layout pass.
VirtualizingPanel
Provides a framework for Panel elements that virtualize their child data collection. This is an abstract class.
A base class for implementing your own virtualizing panel. Only loads visible items to prevent unneeded use of memory and processor. MUCH more performant for sets of items. Probably slightly less performant for items that fit on the screen due to the bounds checking. The SDK only provides one subclass of this, the
VirtualizingStackPanel
.WrapPanel
Positions child elements in sequential position from left to right, breaking content to the next line at the edge of the containing box. Subsequent ordering occurs sequentially from top to bottom or right to left, depending on the value of the Orientation property.
The measure pass is a somewhat complex pass where the largest item for a particular row determines the height of the row and then each item on that row either uses its native height (if it has one) or the height of the row. The layout pass is simple, putting each item one after the other on a row and then continuing onto the next row when there is not enough room for the next item. Medium performance measure pass. Medium to fast performance for the arrangement pass.
帆布
定义一个区域,您可以在该区域内通过相对于 Canvas 区域的坐标明确定位子元素。
由于每个项目都静态分配了一个位置,因此 Canvas 在所有面板的排列过程中具有最佳性能。由于该面板中没有拉伸的概念,因此measure pass也具有出色的性能;每个孩子只是使用其原始大小。
码头面板
定义一个区域,您可以在该区域内相对于彼此水平或垂直排列子元素。
Dockpanel 有一个非常简单的布局方案,其中项目相对于添加的前一个项目一个一个地添加。默认情况下,高度或宽度由项目的本机大小确定(分别基于顶部/底部与左/右),
Dock
如果宽度或高度未定义,则另一个方向由属性确定。中到快速测量通过和中到快速排列通过。网格
定义由列和行组成的灵活网格区域。
如果使用比例调整大小或自动调整大小,这可能是性能最密集的面板。计算子项大小可以是项的本机大小和网格指定的布局的复杂组合。布局也是所有面板中最复杂的。测量通过的慢到中等性能和排列通过的慢到中等性能。
堆栈面板
将子元素排列成可以水平或垂直定向的单行。
StackPanel 使用与其方向相反方向的本机或相对大小来测量其子项,并在其方向的方向上使用本机大小(对齐在这个方向上没有任何作用)。这使其成为该领域的中级表现者。安排通行证很简单,只是按顺序排列项目。可能是这次传球的第二好的表现。测量通过的中等性能和布局通过的快速性能。
虚拟化面板
为虚拟化其子数据集合的 Panel 元素提供框架。这是一个抽象类。
用于实现您自己的虚拟化面板的基类。仅加载可见项目以防止不必要地使用内存和处理器。项目集的性能要高得多。由于边界检查,适合屏幕的项目的性能可能略低。SDK 仅提供了一个子类,即
VirtualizingStackPanel
.包裹面板
将子元素从左到右按顺序定位,将内容分到包含框边缘的下一行。后续排序按从上到下或从右到左的顺序发生,具体取决于 Orientation 属性的值。
测量传递是一个有点复杂的传递,其中特定行的最大项目确定行的高度,然后该行上的每个项目使用其原始高度(如果有的话)或行的高度。布局过程很简单,将每个项目一个接一个地放在一行上,然后在没有足够空间容纳下一个项目时继续到下一行。中等绩效衡量通过。安排通道的中到快速性能。
References:
参考:
Use the Most Efficient Panel where Possible
The complexity of the layout process is directly based on the layout behavior of the Panel-derived elements you use. For example, a Grid or StackPanel control provides much more functionality than a Canvas control. The price for this greater increase in functionality is a greater increase in performance costs. However, if you do not require the functionality that a Grid control provides, you should use the less costly alternatives, such as a Canvas or a custom panel.
尽可能使用最高效的面板
布局过程的复杂性直接基于您使用的 Panel 派生元素的布局行为。例如,Grid 或 StackPanel 控件提供的功能比 Canvas 控件多得多。这种更大的功能增加的代价是性能成本的更大增加。但是,如果您不需要 Grid 控件提供的功能,则应使用成本较低的替代品,例如 Canvas 或自定义面板。
From Optimizing Performance: Layout and Design
The layout system completes two passes for each member of the Children collection, a measure pass and an arrange pass. Each child Panel provides its own MeasureOverride and ArrangeOverride methods to achieve its own specific layout behavior.
During the measure pass, each member of the Children collection is evaluated. The process begins with a call to the Measure method. This method is called within the implementation of the parent Panel element, and does not have to be called explicitly for layout to occur.
First, native size properties of the UIElement are evaluated, such as Clip and Visibility. This generates a value named constraintSize that is passed to MeasureCore.
Secondly, framework properties defined on FrameworkElement are processed, which affects the value of constraintSize. These properties generally describe the sizing characteristics of the underlying UIElement, such as its Height, Width, Margin, and Style. Each of these properties can change the space that is necessary to display the element. MeasureOverride is then called with constraintSize as a parameter.
Note There is a difference between the properties of Height and Width and ActualHeight and ActualWidth. For example, the ActualHeight property is a calculated value based on other height inputs and the layout system. The value is set by the layout system itself, based on an actual rendering pass, and may therefore lag slightly behind the set value of properties, such as Height, that are the basis of the input change. Because ActualHeight is a calculated value, you should be aware that there could be multiple or incremental reported changes to it as a result of various operations by the layout system. The layout system may be calculating required measure space for child elements, constraints by the parent element, and so on. The ultimate goal of the measure pass is for the child to determine its DesiredSize, which occurs during the MeasureCore call. The DesiredSize value is stored by Measure for use during the content arrange pass.
The arrange pass begins with a call to the Arrange method. During the arrange pass, the parent Panel element generates a rectangle that represents the bounds of the child. This value is passed to the ArrangeCore method for processing.
The ArrangeCore method evaluates the DesiredSize of the child and evaluates any additional margins that may affect the rendered size of the element. ArrangeCore generates an arrangeSize, which is passed to the ArrangeOverride method of the Panel as a parameter. ArrangeOverride generates the finalSize of the child. Finally, the ArrangeCore method does a final evaluation of offset properties, such as margin and alignment, and puts the child within its layout slot. The child does not have to (and frequently does not) fill the entire allocated space. Control is then returned to the parent Panel and the layout process is complete.
布局系统为 Children 集合的每个成员完成两次传递,一个测量传递和一个排列传递。每个子面板提供自己的 MeasureOverride 和ArrangeOverride 方法来实现自己特定的布局行为。
在度量传递期间,将评估 Children 集合的每个成员。该过程从调用 Measure 方法开始。此方法在父 Panel 元素的实现中调用,无需显式调用即可进行布局。
首先,评估 UIElement 的原生大小属性,例如 Clip 和 Visibility。这会生成一个名为constraintSize 的值,该值会传递给MeasureCore。
其次,处理FrameworkElement上定义的框架属性,影响constraintSize的值。这些属性通常描述底层 UIElement 的大小特征,例如其高度、宽度、边距和样式。这些属性中的每一个都可以更改显示元素所需的空间。然后使用constraintSize 作为参数调用MeasureOverride。
注意 Height 和 Width 与 ActualHeight 和 ActualWidth 的属性之间存在差异。例如,ActualHeight 属性是基于其他高度输入和布局系统的计算值。该值由布局系统本身根据实际渲染过程设置,因此可能稍微滞后于作为输入更改基础的属性(例如高度)的设置值。由于 ActualHeight 是一个计算值,因此您应该知道,由于布局系统的各种操作,可能会有多个或增量报告的更改。布局系统可能正在计算子元素所需的度量空间、父元素的约束等。度量传递的最终目标是让孩子确定其 DesiredSize,这发生在 MeasureCore 调用期间。DesiredSize 值由 Measure 存储以在内容排列过程中使用。
排列过程从调用排列方法开始。在排列过程中,父 Panel 元素生成一个矩形,表示子元素的边界。该值被传递给ArrangeCore 方法进行处理。
ArrangeCore 方法评估子元素的 DesiredSize 并评估可能影响元素呈现大小的任何附加边距。ArrangeCore 生成一个arrangeSize,它作为参数传递给Panel 的ArrangeOverride 方法。ArrangeOverride 生成子元素的 finalSize。最后,ArrangeCore 方法对偏移属性(例如边距和对齐方式)进行最终评估,并将子项放在其布局槽中。孩子不必(并且经常不必)填充整个分配的空间。然后控制返回到父面板,布局过程完成。
回答by mike_sev
Maybe thiswill help you.
也许这会帮助你。
Not only for panels but also for every application you want to make in WPF.
不仅适用于面板,还适用于您想在 WPF 中制作的每个应用程序。
It concludes WPF drawing & measuring performance.
它总结了 WPF 绘图和测量性能。
It also has a drawing test application, results, and conclusions information for different operating systems that you want to target.
它还有一个绘图测试应用程序、结果和结论信息,适用于您要定位的不同操作系统。
回答by Erick
The panels you mention are Layout panels so a brief overview of the layout system suggests that it's likely not going to be just a simple list of the most efficient panel but how you use the panels that have the largest effect on efficiency and performance.
您提到的面板是布局面板,因此布局系统的简要概述表明,它可能不仅仅是最高效面板的简单列表,而是您如何使用对效率和性能影响最大的面板。
At its simplest, layout is a recursive system that leads to an element being sized, positioned, and drawn. More specifically, layout describes the process of measuring and arranging the members of a Panel element's Children collection. Layout is an intensive process. The larger the Children collection, the greater the number of calculations that must be made. Complexity can also be introduced based on the layout behavior defined by the Panel element that owns the collection. A relatively simple Panel, such as Canvas, can have significantly better performance than a more complex Panel, such as Grid.
简而言之,布局是一个递归系统,它导致元素被调整大小、定位和绘制。更具体地说,布局描述了测量和排列 Panel 元素的 Children 集合的成员的过程。布局是一个密集的过程。Children 集合越大,必须进行的计算次数就越多。还可以根据拥有集合的 Panel 元素定义的布局行为引入复杂性。相对简单的面板(例如 Canvas)可以比更复杂的面板(例如 Grid)具有明显更好的性能。
Each time that a child UIElement changes its position, it has the potential to trigger a new pass by the layout system. Therefore, it is important to understand the events that can invoke the layout system, as unnecessary invocation can lead to poor application performance. The following describes the process that occurs when the layout system is invoked.
每次子 UIElement 更改其位置时,它都有可能触发布局系统的新传递。因此,了解可以调用布局系统的事件很重要,因为不必要的调用会导致应用程序性能不佳。下面介绍一下布局系统被调用时发生的过程。
1. A child UIElement begins the layout process by first having its core properties measured.
1. 子 UIElement 通过首先测量其核心属性开始布局过程。
2. Sizing properties defined on FrameworkElement are evaluated, such as Width, Height, and Margin.
2. 评估 FrameworkElement 上定义的大小属性,例如 Width、Height 和 Margin。
3. Panel-specific logic is applied, such as Dock direction or stacking Orientation.
3. 应用特定于面板的逻辑,例如 Dock 方向或堆叠方向。
4. Content is arranged after all children have been measured.
4.内容是在所有孩子都测量过之后安排的。
5. The Children collection is drawn on the screen.
5. 在屏幕上绘制了 Children 集合。
6. The process is invoked again if additional Children are added to the collection, a LayoutTransform is applied, or the UpdateLayout method is called.
6. 如果向集合中添加了其他子项、应用了 LayoutTransform 或调用了 UpdateLayout 方法,则会再次调用该过程。
See LayoutSystem_Measure_Arrangefor more information on the measuring and arranging of children
有关测量和排列子项的更多信息,请参阅LayoutSystem_Measure_Arrange
Layout is a recursive process. Each child element in a Children collection gets processed during each invocation of the layout system. As a result, triggering the layout system should be avoided when it is not necessary. The following considerations can help you achieve better performance.
布局是一个递归过程。Children 集合中的每个子元素在每次调用布局系统期间都会得到处理。因此,在没有必要时应避免触发布局系统。以下注意事项可以帮助您获得更好的性能。
Be aware of which property value changes will force a recursive update by the layout system.
请注意哪些属性值更改将强制布局系统进行递归更新。
Dependency properties whose values can cause the layout system to be initialized are marked with public flags. AffectsMeasure and AffectsArrange provide useful clues as to which property value changes will force a recursive update by the layout system. In general, any property that can affect the size of an element's bounding box should have a AffectsMeasure flag set to true. For more information, see Dependency Properties Overview.
其值可以导致布局系统初始化的依赖属性用公共标志标记。AffectsMeasure 和 AffectsArrange 提供了有用的线索,说明哪些属性值更改将强制布局系统进行递归更新。通常,任何可能影响元素边界框大小的属性都应将 AffectsMeasure 标志设置为 true。有关更多信息,请参阅依赖属性概述。
When possible, use a RenderTransform instead of a LayoutTransform.
如果可能,请使用 RenderTransform 而不是 LayoutTransform。
A LayoutTransform can be a very useful way to affect the content of a user interface (UI). However, if the effect of the transform does not have to impact the position of other elements, it is best to use a RenderTransform instead, because RenderTransform does not invoke the layout system. LayoutTransform applies its transformation and forces a recursive layout update to account for the new position of the affected element.
LayoutTransform 是影响用户界面 (UI) 内容的一种非常有用的方法。但是,如果变换的效果不必影响其他元素的位置,最好使用 RenderTransform 代替,因为 RenderTransform 不调用布局系统。LayoutTransform 应用其转换并强制递归布局更新以考虑受影响元素的新位置。
Avoid unnecessary calls to UpdateLayout.
避免对 UpdateLayout 进行不必要的调用。
The UpdateLayout method forces a recursive layout update, and is frequently not necessary. Unless you are sure that a full update is required, rely on the layout system to call this method for you.
UpdateLayout 方法强制递归布局更新,并且通常不是必需的。除非您确定需要完整更新,否则请依靠布局系统为您调用此方法。
When working with a large Children collection, consider using a VirtualizingStackPanel instead of a regular StackPanel.
处理大型 Children 集合时,请考虑使用 VirtualizingStackPanel 而不是常规 StackPanel。
By virtualizing the child collection, the VirtualizingStackPanel only keeps objects in memory that are currently within the parent's ViewPort. As a result, performance is substantially improved in most scenarios.
通过虚拟化子集合,VirtualizingStackPanel 只将当前位于父视图端口内的对象保留在内存中。因此,在大多数情况下,性能得到了显着提高。
Optimizing Performance: Layout and Design: This article goes into detail on how to build the tree efficiently and gives a simple list of panels based on their complexity
优化性能:布局和设计:本文详细介绍了如何有效地构建树,并根据面板的复杂性给出了一个简单的面板列表
Canvas (least complext = more efficient and better performance)
画布(最不复杂 = 更高效和更好的性能)
Grid
网格
Other Panels (more complex = less efficient and worse performance)
其他面板(更复杂 = 效率更低且性能更差)
Other performance considerations to pay attention to:Ways to improve WPF UI rendering speed
其他需要注意的性能注意事项:提高WPF UI渲染速度的方法
- Cache everything. Brushes, Colors, Geometries, Formatted Texts, Glyphs. (For example we have two classes: RenderTools and TextCache. Rendering process of each unit addresses to shared instance of both classes. So if two charts have the same text, its preparation is executed just once.)
- Freeze Freezable, if you are planning to use it for a long time. Especially geometries. Complex unfreezed geometries execute HitTest extremely slow.
- Choose the fastest ways of rendering of each primitive. For example, there is about 6 ways of text rendering, but the fastest is DrawingContext.DrawGlyphs.
- Enable Container Recycling. Virtualization brings a lot of performance improvements, but the containers will be disposed and re created, this is the default. But you can gain more performance by recycle containers by setting VirtualizingStackPanel.VirtualizationMode="Recycling"
- From here: There is no practical limit to the amount of nesting that your application can support, however, it is generally best to limit your application to only use those panels that are actually necessary for your desired layout. In many cases, a Grid element can be used instead of nested panels due to its flexibility as a layout container. This can increase performance in your application by keeping unnecessary elements out of the tree.
- 缓存一切。画笔、颜色、几何图形、格式化文本、字形。(例如我们有两个类:RenderTools 和 TextCache。每个单元的渲染过程寻址到两个类的共享实例。因此如果两个图表具有相同的文本,则其准备只执行一次。)
- Freeze Freezable,如果您打算长期使用它。尤其是几何图形。复杂的未冻结几何图形执行 HitTest 非常慢。
- 选择渲染每个图元的最快方式。例如,文本渲染大约有 6 种方式,但最快的是 DrawingContext.DrawGlyphs。
- 启用容器回收。虚拟化带来了很多性能提升,但是容器会被释放和重新创建,这是默认的。但是您可以通过设置 VirtualizingStackPanel.VirtualizationMode="Recycling" 来回收容器来获得更多性能
- 从这里开始:对于您的应用程序可以支持的嵌套数量没有实际限制,但是,通常最好将您的应用程序限制为仅使用所需布局实际需要的面板。在许多情况下,可以使用 Grid 元素代替嵌套面板,因为它具有作为布局容器的灵活性。这可以通过将不必要的元素排除在树之外来提高应用程序的性能。